home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / os2 / srefv12i.zip / srefiltr.80 < prev    next >
Text File  |  1997-04-18  |  85KB  |  2,392 lines

  1. /* SRE-Filter main program, ver 1.2i
  2.   Copyright for the world, Feb 1997, Daniel Hellerstein.
  3.   Liability,etc. strictly denied (see the READ.ME file);
  4.   but feel free to use and modify this code as you see fit.
  5. */
  6.  
  7. /*     ---------- User Changeable Parameters     -------------
  8.  
  9. There are several variables set here that you may want to change:
  10.  
  11.   always_check_privs:  Flag to "check client privileges even if it's a public url"
  12.   BackupServerList: ip addresses of servers to distribute to under load
  13.   dir_cache_size: size of the directory-listing cache
  14.   dir_cache_duration: lifespan of entries in the directory-listing cache
  15.   delay_seconds: time delay for sre-filter to check parameter files for changes
  16.   hit_superuser_suppress: modify HIT_OWNER_SUPPRESS to check for SUPERUSERS
  17.   ncsa_ismap: substring(s) that signals "this is an NCSA mappable image request"
  18.   cern_ismap: substring(s) that signals "this is a CERN mappable image request"
  19.  
  20.   key_preface: optional preface for server side include keywords
  21.   logon_limit:  maximum # of logon attempts, per minute per client
  22.   LoadThreshold: Used with BACKUPSERVERLIST (load at which transfer occurs)
  23.   message_scramble: used by messages boxes to encode passwords
  24.   no_no_record: Suppress the !NORECORD directive
  25.   record_cache_lines: Size of RECORD_ALL_FILE cache
  26.   save_state: turn on sre-filter's "save request specific info to file" option
  27.   sem_maxwait: waiting time till threads check their queue
  28.   ssi_extensions: extensions for which the ssi_shtml_only parameter applies
  29.   ssi_cache_size: size of the ssi-cache
  30.   ssi_cache_duration: lifespan of entries in the ssi-cache
  31.   ssi_cache_stamp: Type of "trigger" check (used with ssi-cache)
  32.  
  33.   See INITFILT.DOC for a discussion of what these do.
  34.  
  35.   Note: The essential difference between parameters here, and in INITFILT.80,
  36.         is that these are updated ONLY when GoServe is re-started.
  37.         In contrast, INITFILT.80 parameters are checked (and possibly updated)
  38.         every "delay_seconds" (default value is 15) seconds.
  39.  
  40.         The notion is that these are more fundamental paramters, which
  41.         will need modification less frequently then INITFILT.80 parameters.
  42.  
  43.                            ------------------                              */
  44.  
  45. /* set to 1 if you want to check for privileges  (using inhouseips, owner, additional privileges,
  46. and authorization stuff) when the request string matches a public_URL (set to 0 to NOT check for these privs)
  47. This may "unnecessarily slow things down", but may be required if further privilege checks are
  48. done by sre-filter addons */
  49. always_check_privs=1
  50.  
  51. /* This spaced delimited list contains ip addresses of backup servers
  52.   It's used in conjunction with LOADTHRESHOLD */
  53. BackupServerList = 'www.yahoo.com '
  54.  
  55. /* set the "duration" of entries in the directory-listing cache.
  56.   This is used by the !dir facility of SRE-Filter */
  57. dir_cache_duration=3
  58.  
  59. /* set the maximum size (in Kbytes) of the directory-listing-cache.
  60.   This is used by the !dir facility of sre-filter */
  61. dir_cache_size=1000
  62.  
  63. /* Delay_seconds controls how frequently sre-filter checks input files
  64. * for updates.  Larger values mean more time between checks. */
  65. delay_seconds=15
  66.  
  67. /* if non-zero, then if hit_owner_suppress is on, also
  68.    check if the client has a superuser privilege (that is, if non-0 then
  69.    HIT_OWNER_SUPPRESS will treat owners and superusers equivalently)
  70.    Note: if HIT_OWNER_SUPPRESS is not enabled, then hit_superuser_suppress
  71.          is ignored */
  72. hit_superuser_suppress=1
  73.  
  74. /* indicators for "mappable image" requests: NSCA and CERN style .MAP files*/
  75. ncsa_ismap='mapimage/ mapnsca/ cgi-bin/mapimage '
  76. cern_ismap='mapcern/ cgi-bin/htimage/'
  77.  
  78. /* if non-zero, modifies the REPLACE keywords */
  79. key_preface=0     /* key_preface="#" is NOT allowed! */
  80.  
  81. /*  Allow this many simultaneous connections before attempting load balancing
  82.     It's used in conjunction with BACKUPSERVERLIST */
  83. LoadThreshold = 0               /* 0 means "do not perform load balancing */
  84.  
  85. /* sets the maximum number of unsuccessful "logon" attempts, per minute
  86. * per ip address.  Set to 0 for "unlimited" attempts.
  87. * Note that a value of 1 may cause problems. */
  88. logon_limit=0
  89.  
  90. /* this is used to "encrypt" domessage passwords.  change it
  91. * for a wee bit extra security */
  92. message_scramble=12415
  93.  
  94. /* if you want to suppress the use of the !NORECORD directive,
  95.    set NO_NO_RECORD=1 */
  96. no_no_record=0
  97.  
  98. /* this sets the size (in entries_ of the "recordall_file" cache.
  99. * If you do NOT want to cache the recordall_File, set this to 0
  100. * Enabling caching (by using non-0 values0 speeds up throughput,
  101. * but risks minor errors in counts) */
  102. record_cache_lines=0
  103.  
  104. /* Enable saving of request specific info to a temporary file (for use
  105. by external routines, including SREF_READ_STATE and SREF_WRITE_STATE).
  106. Set to 0 to suppress this, 1 to turn it on */
  107. save_state=0
  108.  
  109. /* controls "wait on queue" maximum time delay */
  110. sem_maxwait=15000
  111.  
  112. /* the list of "SSI capable" extensions (used if SSI_SHTML_ONLY='YES') */
  113. ssi_extensions=' SHT SHTML HTML-SSI HTM-SSI '
  114.  
  115. /* Set the size of the server-side-include (SSI) cache, in kilobytes.
  116.   Once cached files (saved to disk) exceed this amount,
  117.   older entries will be deleted.
  118.   A value of 0 means "do NOT cache".
  119.   Example: 1000 means  1M. */
  120. ssi_cache_size=5000
  121.  
  122. /* set the "lifespan" of ssi-cache entries, in days (fractional values
  123.    are allowed).  SSI-cache entries older then this will be deleted */
  124. ssi_cache_duration=1
  125.  
  126. /* set the "type" of trigger checking of ssi-cache entries. You can
  127. the time (TIME), the date (DATE), the time and date (TIMEDATE),
  128. the size (SIZE), or all 3 (ALL). */
  129. ssi_CACHE_stamp='ALL'
  130.  
  131. /*      --------- END OF USER CHANGEABLE SECTION  ----------------*/
  132. /*      --------- END OF USER CHANGEABLE SECTION  ----------------*/
  133. /*      --------- END OF USER CHANGEABLE SECTION  ----------------*/
  134. /*      --------- END OF USER CHANGEABLE SECTION  ----------------*/
  135.  
  136.  
  137. /* Do NOT change parameters below this line (unless you like to program) */
  138.  
  139. /*--------------   Load REXX libraries ----- */
  140. /* Load up advanced REXX functions */
  141. foo=rxfuncquery('sysloadfuncs')
  142. if foo=1 then do
  143.   call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
  144.  
  145.   call SysLoadFuncs
  146. end
  147. foo=rxfuncquery('rexxlibregister')
  148. if foo=1 then do
  149.  call rxfuncadd 'rexxlibregister','rexxlib', 'rexxlibregister'
  150.  call rexxlibregister
  151. end
  152.  
  153.  
  154. /* ---------Get stuff sent from GOSERVE program -----------------*/
  155. parse arg source, request , seloriginal
  156.  
  157.  
  158. if request=" " then return 'NODATA'     /* netscape sometimes does this */
  159.  
  160. source0=source ; request0=request ; selrec=seloriginal
  161. parse var source myaddr port transaction who whoport . /* Often useful */
  162. parse var request verb uri protocol .        /* split up the request line */
  163.  
  164. enmadd="SREF_"||port||"_"
  165. basesem='\SEM32\'||enmadd
  166. os2e='os2environment'
  167. gospid=dospid()
  168.  
  169. /* Set: force_auth force_norecord specific_mime del_send */
  170. call  modify_seloriginal   /* strip out !directives from seloriginal */
  171.  
  172. if key_preface="#" then key_preface=""  /* # not allowed as key_preface */
  173.  
  174. /* ---- Do we need to initialize sre-filter ?  --- */
  175. /* Note: we do not use transaction number, since transaction is NOT reset
  176.    when the filter is changed.  Hence, the use of this rather convoluted scheme */
  177. thesem=basesem
  178. sem_status=eventsem_query(thesem)
  179. if sem_status<0 then do
  180.    servdir=directory()          /* should NOT be on-the-fly-changeable */
  181.    oo=value(enmadd||'SERVDIR',servdir,'os2environment')
  182.  
  183. /* to avoid trouble, do not allow any other requests while sre-filter is initializing */
  184.   if oo<>"" then do
  185.      cl=extract('clients')
  186.      if cl=0 then do
  187.         call pmprintf(' It appears that the SRE-Filter initialization failed ')
  188.         call pmprintf(' Is your net connection working? ')
  189.         string ' Sorry: Server Initialization Failure. '
  190.      end
  191.      else do
  192.          call pmprintf(' 2nd request while initializing: deny access for now ')
  193.      end
  194.      string ' Server is initializing, please try again in a few minutes. '
  195.      exit ' '
  196.   end
  197.  
  198.  /* first call, start up the helper threads ! */
  199.  
  200.   initfilt_file=servdir||"\INITFILT."||port
  201.   aa2=eventsem_close(thesem)
  202.   afilt2=servdir'\srefmon.cmd'
  203.   moreargs=loadthreshold||','||backupserverlist||','||delay_seconds||','||message_scramble||','||record_cache_lines||','||logon_limit||','||ssi_extensions
  204.   moreargs=moreargs||','ssi_cache_size||','||ssi_cache_duration||','||SSI_CACHE_STAMP||','||save_state||','||no_no_record
  205.   foo=rexxthread('f',afilt2,gospid,thesem,servdir,PORT,enmadd,sem_maxwait,moreargs)
  206.  
  207.   call pmprintf(' Note: SRE-FILTER monitor started on thread 'foo)
  208.  
  209. /* allow plenty of time for initialization thread to do it's business */
  210.    do forever   /* wait for filter monitor to say "go ahead" */
  211.         foo=eventsem_wait(thesem,2000)
  212.         if foo<>0 then do
  213.            call delay(.2)
  214.            iterate
  215.         end
  216.         call pmprintf('SRE-Filter initialization complete ')
  217.        leave
  218.    end
  219.  end        /* wait till thesem is set */
  220.  
  221. /* check if load balancing needed */
  222. if loadthreshold>0 & BackupServerList \= '' then do
  223.   'EXTRACT CLIENTS'
  224.   if Clients > LoadThreshold then do
  225.         foo=completed()
  226.         if foo=0 then do
  227.           i1=transaction//(words(backupserverlist)+1)
  228.           if i1=0 then i1=1
  229.           auri=word(backupserverlist,i1)
  230.           auri2='http://'||auri||'/'||seloriginal
  231.           'HEADER ADD Location:' auri2
  232.           'RESPONSE HTTP/1.0 302 Moved Temporarily'  /* Set HTTP response line */
  233.           'STRING  Redirect to backup server at '|| auri
  234.           post_filter_message=' Redirected to '||auri
  235.           response_status='302 0'
  236.           signal do_post_filter
  237.       end
  238.    end
  239. end                     /* end of load balancing check */
  240.  
  241. /* save some request specific variables? */
  242. if save_state=1 then do
  243.    verbose=get_value('VERBOSE',0)
  244.    tcachfile=sref_save_state(source,request,seloriginal,enmadd,port,verbose)
  245. end
  246.  
  247. /* check for special message generated by srefquik */
  248. transaction=strip(upper(transaction))
  249. puburl=""
  250. if abbrev(transaction,'PUBFILE_')=1 then do
  251.       transaction=delstr(transaction,1,8)
  252.       parse var seloriginal puburl seloriginal
  253.       selrec=seloriginal
  254. end
  255. if abbrev(transaction,'NOFILE_')=1 then do
  256.       transaction=delstr(transaction,1,7)
  257.       response_status= not_found_response(seloriginal,' Document not found ',' ')
  258.       selrec=' '
  259.       post_filter_message="Bad request for public file "
  260.       signal do_post_filter
  261. end
  262. /*  -----------------Tidy up some initialization parameters ------------ */
  263.  
  264. skip1:          /* if pub_url available, skip here */
  265. privset=' '
  266. owners=' '
  267. current_hit.num=0
  268. current_hit.item=""
  269. current_hit.mess1=""
  270. current_hit.mess2=""
  271. outbig=''
  272. replines.0=-1
  273. interp_data=0
  274. virtual_dir.0=0
  275. cache_status="NOCACHE"
  276. is_public=0
  277. is_alias=0
  278. from_auth=0
  279. post_filter_message=" "
  280. tmp.0=0                 /* for use by INTERPRET blocks */
  281. crlf='0d0a'x            /* might need this */
  282. nhosts=0
  283. myhost=0
  284. got_def=0
  285. nopostf=' '
  286. do_htaccess=0    /* 0=don't do, 1= do htaccess */
  287. used_file=' '   /* the file this is the target of the request */
  288. gp_param=0      /* getpost optional parameter */
  289. logon_fail_file=0
  290. access_fail_file=0
  291. response_status=' '
  292. serverport=port
  293. internal_procs='SENDFILE SHOWDIR DIR GETAFILE DOSEARCH ASKMESSBOX VIEWMESS GET_URL PUT_FILE MESSAGE '
  294.  
  295. ncsa_ismap=strip(upper(ncsa_ismap))
  296. cern_ismap=strip(upper(cern_ismap))
  297.  
  298. clientname0=0
  299. isinhouse=0
  300.  
  301. mytid=dostid()
  302.  
  303. mysem=thesem||"t"||mytid
  304. myqueue="SREF_"||port||'_t'||mytid
  305. servdir=value(enmadd||'SERVDIR',,os2e)
  306.  
  307. nhosts=value(enmadd||'HOSTS.0',,os2e)
  308.  
  309. no_postfilter=0 ; no_virtual=0
  310.  
  311. servername=0
  312.  
  313. /* check on multiple hosts */
  314. if nhosts>0 then do
  315.    stuff=sref_host_info(myaddr,nhosts,enmadd)
  316.  
  317.    if stuff<>0 then do
  318.       parse var stuff  servername ',' host_nickname  ',' ddir
  319.       host_nickname=strip(host_nickname); ddir=strip(ddir)
  320.       default=strip(default) ; servername=strip(servername)
  321.    end
  322. end
  323. if servername=0 then do  /* nhosts=0, or no match in get_host_info */
  324.     ddir=datadir()
  325.     servername=servername()
  326.     host_nickname=' '
  327. end
  328.  
  329. /* if !DELSEND special directive, MUST be under tempfile_dir */
  330. if del_send=1 then do
  331.    ddir=get_value('TEMPFILE_DIR',0)
  332. end
  333. if ddir="" then do
  334.       response_status= not_found_response(seloriginal,' Document not found ',' ')
  335.       selrec=' '
  336.       post_filter_message="Bad request for public file "
  337.       signal do_post_filter
  338. end
  339.  
  340.  
  341. verbose=get_value('VERBOSE')
  342.  
  343. if verbose>3 then say " Using data directory= " ddir seloriginal
  344.  
  345. if  VERBOSE>1 & host_nickname<>' ' then
  346.   call pmprintf(' Request to host: ' host_nicknAME)
  347.  
  348. tempdata_dir=get_value(tempdata_dir)
  349.  
  350. tdir=strip(TEMPDATA_DIR,'t','\')||'\'
  351. tempfile=tdir'$'transaction'.'port                      /* Often used */
  352. if stream(tempfile,'c','query exists')<>' ' then  do /* just in case of prior crash?*/
  353.    say " Warning: old tempfile needs to be removed: " tempfile
  354.    tempfile=dostempname(tdir'$??????.'port) /* failure is verrry unlikely! */
  355. end
  356.  
  357.  
  358. check_alias=get_value('CHECK_ALIAS')
  359. home_dir=get_value('HOME_DIR')
  360. htaccess_file=get_value('HTACCESS_FILE')
  361. do_htaccess=get_value('DO_HTACCESS')
  362. default=get_value('DEFAULT')
  363. no_include=get_value('NO_INCLUDE')
  364. no_processing=get_value('NO_PROCESSING')
  365. no_interpret_code=get_value('NO_INTERPRET_CODE')
  366. auto_header=get_value('AUTO_HEADER')
  367.  
  368. home_name=get_value('HOME_NAME')
  369. not_found_url=get_value('NOT_FOUND_URL')
  370. not_found_url=sref_replacestrg(not_found_url,'HOME_NAME',home_name)
  371.  
  372.  
  373. /* ---------------------- End of initialization section   ------------*/
  374.  
  375.  
  376. /* done initializing -- now process the request . */
  377.  
  378. /* 1) call a pre-filter (it might EXIT back to GoServe)
  379.      The pre-filter should check for completion!
  380.     Note that pre-filter is ALWAYS called, even if cached transfer occurred*/
  381.  
  382. pre_filter=get_value('PRE_FILTER')
  383.  
  384. prefilter_name=get_value('PREFILTER_NAME')
  385. auto_name=get_value('AUTO_NAME')
  386. first_ht_auto=1                 /* allow just one auto_name replacement by htaccess */
  387.  
  388.  
  389. /* 1a) make personallized queue and semaphore */
  390. call make_semmi
  391. if dienow=0 then return 0           /* error, give up */
  392.  
  393. /* 1b) if pub_url, then couldn't be a first prefilter, so skip. Otherwise.. */
  394. if pre_filter="FIRST" & puburl="" then do
  395.     prefilter_result=do_prefiltr(' ')
  396.     parse var prefilter_result status ',' prefilter_result
  397.     a=done_it(status,"Pre-filter processed: "||prefilter_result)
  398.     if a=1 then do
  399.           post_filter_message="Pre-filter used"
  400.           signal do_post_filter
  401.     end
  402. end
  403.  
  404. /* 2) MAKE SURE THE REQUEST IS STILL ACTIVE!!
  405.      (IF CACHING OCCURED, IT MIGHT NOT BE !! */
  406. aa=done_it(0,'From cache: '||seloriginal)
  407.  
  408.  
  409. /* already been completed (possibly from cache) */
  410. if aa=1 then DO
  411.  
  412. /* a !norecord request */
  413.    if force_norecord=1 then return 0
  414.  
  415. /* is it a public url with NORECORD option */
  416.    stuff=sref_public_urls(seloriginal,host_nickname,enmadd,,,,,1)
  417.  
  418.    if stuff=1 then return ' '
  419.  
  420. /* check access file for nopostfilter */
  421.   aline=wait_queue('ACCESS',seloriginal,allow_access)
  422.   parse var aline istat ',' accprivs ',' accopts ',' .
  423.   if wordpos('NO_POSTFILTER',accopts)>0  then return ' '
  424.  
  425. /* postfilter not suppressed ... do it */
  426.     post_filter_message="Cached file sent:"||seloriginal
  427.     response_status='200 '||extract('bytessent')
  428.     signal do_post_filter
  429. END
  430.  
  431. /* 3) Check for basic grooviness */
  432. if left(protocol,4)\='HTTP' & protocol\='' then do
  433.           response_status=response('badreq', 'specified a protocol that was not HTTP')
  434.           post_filter_message='Bad HTTP Protocol '
  435.           signal do_post_filter
  436. end
  437. /* 4) Is it one of the public_urlS ??. IF so, skip logons,
  438.      etc (but do aliases and ssi's). */
  439.  
  440. if puburl<>"" then do           /*PUBURL MAYBE SET BY SREFQUIK */
  441.     parse var puburl useliteral ',' puburl ; sel=strip(puburl)
  442.     if pos('NORECORD',useliteral)>0 then no_postfilter=1 /* LITERALS WILL NEVER MAKE IT HERE */
  443.     is_public=1 ; do_htaccess=0
  444.     public_privs=get_value('public_privs')
  445.     privset=" PUBLICFILE "||PUBLIC_PRIVS
  446.     cache_status=' '     /* it's public, so you might as well allow caching */
  447. end
  448. else do
  449.   sel=seloriginal
  450.   num_pub=get_value("NUM_PUBLIC_URLS")
  451.   if num_pub>0 then do
  452.      stuff=sref_public_urls(sel,host_nickname,enmadd,ddir,home_dir,verbose,specific_mime)
  453.      parse var stuff  astat litmatch norecmatch ',' amessage
  454.      astat=strip(astat) ; litmatch=strip(litmatch); norecmatch=strip(norecmatch)
  455. /* astat:0=no, 1=yes, litmatch:1=litera, norecmatch:1= norecord  */
  456.      select
  457.         when astat=1 & litmatch<>1 then do
  458.           is_public=1 ; do_htaccess=0
  459.           if norecmatch=1 then no_postfilter=1
  460.           public_privs=get_value('public_privs')
  461.           privset=" PUBLICFILE "||PUBLIC_PRIVS
  462.           cache_status=' '     /* it's public, so  allow caching */
  463.         end
  464.         when astat=1 & litmatch=1 then do  /* sref_public_urls responded to literal puburls */
  465.            if norecmatch=1 then return ' '
  466.            post_filter_message=strip(amessage)
  467.            signal do_post_filter
  468.         end
  469.         otherwise
  470.               nop
  471.      end
  472.   end           /* Num_pub */
  473. end             /* puburl */
  474.  
  475.  
  476. if is_public=1  then do  /* is public url,  get privs? */
  477.   if always_check_privs=1 then do
  478.      if  wordpos(who,owners)>0 then  privset=privset||" SUPERUSER INHOUSE "||INHOUSE_PRIVS
  479.  
  480.      check_add_privs=get_value('CHECK_ADD_PRIVS')  /* LOOK FOR ADDITIONAL PRIVILEGES? */
  481.  
  482.      if check_add_privs=1 then do
  483.          aprefix=strip(get_value('ADD_PRIVS_PREFIX'))
  484.  
  485.          ap2=sref_get_add_privs(host_nickname,who,port,enmadd,tempdata_dir,verbose)
  486.          ap2=translate(ap2,' ','&')    /* correct entry errors (& for RESOURCE privs only  */
  487.          do iw=1 to words(ap2)
  488.             privset=privset||' '||aprefix||strip(word(ap2,iw))
  489.          end
  490.  
  491.      end
  492.      CALL get_user_privs 0    /* get inhouse, authorization, and own-name privs */
  493.      if save_state=1 then foo=sref_write_state('PRIVSET',privset)
  494.   end
  495.  
  496.  aline=wait_queue('ACCESS',seloriginal,allow_access)  /* get access privileges */
  497.  parse var aline . ',' . ',' accopts ',' .
  498.  if wordpos('NO_POSTFILTER',upper(accopts))>0 then no_postfilter=1
  499.   signal  do_alias      /*  do the verb (skip logons, access check, etc */
  500. end
  501.  
  502. /* 5) Do we check for logon rights, etc. */
  503. /* 5a) check for bad ip */
  504. username=' '            /* just in case */
  505.  
  506. owners=get_value('OWNERS')
  507. mdo=sref_badips(who,enmadd,host_nickname)
  508. if mdo=1 then do  /* he is a bad ips, but we let owner and inhouse override it */
  509.   if wordpos(who,owners)=0 then do    /* not an owner */
  510.     call goodips(who)
  511.     if result=0 then do  /* not an inhouseips */
  512.           response_status=response('unauth', 'You are not permitted access to this web server ')
  513.           post_filter_message="Unauthorized access "
  514.           signal do_post_filter
  515.     end
  516.     else do
  517.         if verbose>0 then call pmprintf(' Note: 'who' is a badips and inhouseips -- ignoring badips! ')
  518.         username=who
  519.     end
  520.   end
  521.   else do
  522.      if verbose>0 then  call pmprintf(' Note: 'who' is  badips and an owner -- ignoring badips! ')
  523.      username='OWNER'
  524.   end
  525. end
  526.  
  527. /* 5b) Do a DNS check ? */
  528. dns_check=get_value('dns_check')
  529. if dns_check="YES" then do
  530.    clientname0=clientname()
  531.    if clientname0=who then do
  532.         audit ' Denied access to ' who
  533.         response_status=response('unauth', 'No client name found, access to this web server is denied. ')
  534.         post_filter_message="No client name found, access denied "
  535.         signal do_post_filter
  536.     end
  537. /*    say " DNS check ok: " clientname0 */
  538. end
  539.  
  540.  
  541. /* 5c) Check user/pwd/privilege list  */
  542. checklog=get_value('CHECKLOG')
  543. inhouse_privs=get_value('INHOUSE_PRIVS')
  544. the_realm=get_value('THE_REALM')
  545. allow_access=get_value('ALLOW_ACCESS') ;
  546. cache_status='NOCACHE'
  547.  
  548. select
  549.      when checklog="YES" & (sel=" " ) then do
  550.         dologon=1
  551.      end
  552.      when checklog="INHOUSE" | checklog="ALWAYS" then do
  553.          dologon=1
  554.      end
  555.      otherwise do
  556.          dologon=0
  557.          if allow_access="YES" | allow_access="YES_NOCHECK" then  cache_status=' '
  558.      end
  559.  end
  560. /* do logons, etc ... */
  561.  
  562.  if  wordpos(who,owners)>0 then do   /* owners are treated with kid gloves */
  563.          privset="SUPERUSER INHOUSE "||inhouse_privs   /* also give inhouse privs  */
  564.          CALL get_user_privs 1,1  /* get user privs */
  565.          username="OWNER"
  566.  end
  567.  else do                       /* non owners get the third degree? */
  568.      if  dologon=1 then do       /* yup, book 'em */
  569.          logon_fail_file=get_value('LOGON_FAIL_FILE')
  570.          userinfo=do_logon(who,inhouse_privs)    /* if no match, exits (for new pwd or say sorry)  */
  571.          if gotauser=0 then do
  572.                 post_filter_message="Logon failed "
  573.                 response_status=userinfo
  574.                 signal do_post_filter
  575.          end
  576.          parse var Userinfo lstat username privset
  577.          username=strip(username)
  578.         /*very tough--only inhouse allowed (explicit or as a privilege)?*/
  579.         if checklog="INHOUSE" & wordpos('INHOUSE',privset)=0 & wordpos('SUPERUSER',privset)=0 then  do
  580.            response_status=response('unauth', 'Sorry, access currently limited to in-house users ')
  581.            post_filter_message="Logon denied to non-inhouse user "
  582.            signal do_post_filter
  583.         end     /* not inhouse */
  584.  
  585. /* If here, welcome ! */
  586.         if verbose>0 then call pmprintf(host_nickname '// 'seloriginal' :request from: ' username '(privs: ' privset)
  587.  
  588.      end                /* dologon =1 */
  589.  
  590. /* If here, then no logons required, */
  591.      else do
  592.         CALL get_user_privs 1    /* go get inhouse, user; but NOT ownname privileges */
  593.      end                 /* check if logon rwquired */
  594.  end                    /* not superuser */
  595.  
  596.  
  597. /* add public_privs to everyone */
  598.  public_privs=get_value('public_privs')
  599.  privset=privset||' '||public_privs
  600.  
  601. /* add "username " to privset (this step may be redundant, but... ? */
  602. addname=get_value('add_user_name')
  603. if addname=1 then do
  604.   if wordpos(upper(username),upper(privset))=0 then
  605.        privset=privset||' '||username
  606. end
  607.  
  608. /* check for dynamic privileges ? */
  609. check_add_privs=get_value('CHECK_ADD_PRIVS')
  610. if check_add_privs=1 then do
  611.        aprefix=strip(get_value('ADD_PRIVS_PREFIX'))
  612.        ap2=sref_get_add_privs(host_nickname,who,port,enmadd,tempdata_dir,verbose)
  613.        do iw=1 to words(ap2)
  614.           privset=privset||' '||aprefix||strip(word(ap2,iw))
  615.        end
  616.        privset=translate(privset,' ','&')  /* correct entry errors */
  617. end
  618.  
  619. if save_state=1 then foo=sref_write_state('PRIVSET',privset) /* save privset*/
  620.  
  621. isinhouse=wordpos('INHOUSE',upper(privset))  /* flag for inhouse client */
  622.  
  623. if wordpos('SUPERUSER',upper(privset))>0 then do
  624.    no_processing=0 /* make sure superusrs are unimpeded */
  625.    no_interpret_code=0
  626. end
  627.  
  628. /*  6) now check access file for access and other conditions, for this url. */
  629.  
  630.   aline=wait_queue('ACCESS',seloriginal,allow_access)
  631.   parse var aline istat ',' accprivs ',' accopts ',' urlrealm ',' afail_file ',' adv_opts
  632.   afail_file=strip(afail_file)
  633.  
  634. /* Note: access is checked for all request (checked above for public_Urls)
  635.    istat=0 for all non-matched urls */
  636.  
  637. /* should we disallow */
  638.   ok1=0
  639.   if wordpos('SUPERUSER',privset)>0 then ok1=1
  640.   if ok1=0 then do
  641.     select
  642.       when allow_access="YES" | allow_access="YES_NOCHECK"  then
  643.         ok1=1
  644.       when allow_access="INHOUSE" & isinhouse=1 then
  645.         ok1=1
  646.       otherwise
  647.         if istat<>0 then DO      /* if istat=0, then ask_auth below */
  648. /* add own-resource privilege? */
  649.            addreso=get_value('ADD_RESOURCE_NAME')
  650.            if addreso=1 theN DO
  651.              PARSE UPPER VAR SELORIGINAL ACTION '?' .
  652.              accprivs=accprivs||' '||action
  653.            end
  654.            ok1=check_privs(privset,accprivs)
  655.          end
  656.     end
  657.   end
  658.  
  659. /* if acess to this url not permitted, let client try "another" name,
  660.   OR send a response file */
  661.  
  662.  if ok1=0 then do
  663.      post_filter_message='Ask Authorization (access file)'
  664.  
  665.      access_fail_file=get_value('ACCESS_FAIL_FILE')
  666.      if access_fail_file=0 | force_auth=1 | ,
  667.         (access_fail_file<>-1 & reqfield('Authorization')=' ') then do
  668.            response_status=ask_auth(the_realm,urlrealm)         /* just ask authoriaztion */
  669.      end
  670.  
  671.      if afail_file=' ' then afail_file=access_fail_file
  672.      awebmaster=get_value('WEBMASTER')
  673.      if afail_file=-1 then do           /* terse denial */
  674.         response_status=response('unauth','Access denied')  /* flat out denial */
  675.      end
  676. /* possible custom message */
  677.      response_status=sref_fail(servername,seloriginal,afail_file,verbose,the_realm,'access failure',awebmaster,'No access privileges to this resource')
  678.      signal do_post_filter
  679.  
  680.   end
  681.  
  682. /* if here, privileges were satisfied */
  683.  
  684. /* 6a) lookup/set permissions for this url */
  685. /* Now check for ssi and ssp privs */
  686.  aok=wordpos('NO_SSI',accopts)
  687.  if aok<>0 then
  688.           no_include=1
  689.  
  690.  aok=wordpos('NO_SSP',accopts)
  691.  if aok<>0  & wordpos('SUPERUSER',privset)=0 then
  692.        no_processing=1
  693.  
  694.  aok=wordpos('NO_CODE',accopts)
  695.  if aok<>0  & wordpos('SUPERUSER',privset)=0 then
  696.        no_interpret_code=1
  697.  
  698.  
  699. /* see if this should be cached */
  700.    aok=wordpos('CACHE',accopts)
  701.    if aok<>0 then
  702.        cache_status=' '
  703.  
  704. /* see if suppress alias and/or suppress of this url*/
  705. if wordpos('NO_ALIAS',accopts)>0 then
  706.     check_alias=0
  707. if wordpos('NO_POSTFILTER',accopts)>0 | force_norecord=1 then
  708.         no_postfilter=1
  709. if wordpos('NO_VIRTUAL',accopts)>0 then
  710.         no_virtual=1
  711. if wordpos('NO_HTACCESS',accopts)>0 then
  712.        do_htaccess=0
  713. if wordpos('SUPERUSER',privset)>0 then
  714.        do_htaccess=0
  715.  
  716. if del_send=1 then do  /* del_send has limited "mobility" */
  717.    cache_status='NOCACHE' ; no_virtual=1 ; check_alias=0
  718. end
  719.  
  720. /* check on advanced options */
  721. if adv_opts<>" " then do
  722.       wd=get_value(workdata_dir)
  723.       foo=strip(wd,'t','\')||'\'||strip(adv_opts)
  724.       adv_opts_file=stream(foo,'c','query exists')
  725.       if adv_opts_file="" then do
  726.           say "Warning: missing advanced options file: " adv_opts " ("seloriginal
  727.       end
  728.       else do
  729.          adv_opts=charin(adv_opts_file,1,chars(adv_opts_file))
  730.       end
  731. end
  732.  
  733.  
  734. /* 7) call prefilter */
  735. /* call a pre-filter (it might EXIT back to GoServe) */
  736. if pre_filter="YES" then do
  737.     prefilter_result=do_prefiltr(privset)
  738.     parse var prefilter_result status ',' prefilter_result
  739.     a=done_it(status,"Pre-filter processed: "||prefilter_result)
  740.     if a=1 then do
  741.           post_filter_message="Pre-filter used"
  742.           signal do_post_filter
  743.     end
  744. end
  745.  
  746. /* 8) do aliases (including blank = default */
  747.  
  748.  if sel=' '  then do
  749.       sel=default
  750.       selrec='DEFAULT='||sel
  751.       got_def=1
  752.  end
  753.  else do
  754.    if substr(sel,1,1)='?' then do   /* simple, or with options */
  755.        sel=default||sel   /* default MUST be an HTML document  */
  756.        selrec='DEFAULT='||sel
  757.        got_def=1
  758.    end
  759.  end
  760.  
  761. /* check for redirection default */
  762. if got_def=1 & abbrev(upper(sel),'HTTP://')=1 then do
  763.     dog=isa_move(sel,servername,serverport)
  764.     if dog<>0 then do
  765.        post_filter_message="Alias invoked redirect on default "
  766.        signal do_post_filter
  767.     end
  768. end
  769.  
  770. /* Now see if the ACTION is really an alias for some other action */
  771.  
  772. do_alias: nop                           /* jump here if is_public */
  773.  
  774. if check_alias<>0 then do      /*see if 'action' is an alias for something else*/
  775.   aline=wait_queue('ALIAS',seloriginal)
  776.   parse var aline istat newsel
  777.   if istat>0 then do
  778.      sel=strip(newsel)
  779.      if verbose>0 then say " Alias #  resolves to: " sel
  780.      is_alias=1
  781.   end
  782.  
  783. /* redirection? or absolute file */
  784.   if is_alias=1 then do
  785.     dog=isa_move(sel,servername,serverport)
  786.     if dog<>0 then do
  787.        post_filter_message="Alias invoked redirect "
  788.        signal do_post_filter
  789.     end
  790. /* is this a "send non-data directory file" action
  791. (OBSOLETE, use of virtual directories recommended)*/
  792.     if abbrev(upper(sel),"!TRANSFER=") then do
  793.       parse var sel action '?' awords
  794.       response_status=send_non_datadir(action)
  795.       post_filter_message="Transfered non-data directory file: "||awords
  796.       signal do_post_filter
  797.    end
  798.  end
  799. end                             /* alias checking */
  800.  
  801. /* 9) See if a "home_dir" flag (a ~) is present.  If so, replace it */
  802. parse var sel action '?' awords
  803. foo1=pos('~',action)
  804. if foo1>0 then do            /* do ~ for home_dir replacement, with $ option */
  805.   action=sref_home_dir(action,home_dir)
  806.   action=strip(action,'l','/')
  807. end
  808. if pos('?',sel)>0 then
  809.     sel=action||'?'||awords
  810.  else
  811.      sel=action
  812.  
  813.  
  814. /*  The next stuff is for GET requests only, so skip otherwise */
  815.  
  816. if verb<>"GET" | left(sel,1)="!" then signal do_verb
  817.  
  818. /* 10) Check sel to see if it's a "no extension" variant. If so, NOEXT_TYPE dictates
  819.   what to do. */
  820.  
  821. noexttype=upper(get_value('NOEXT_TYPE'))
  822. if pos("CGI-BIN/",upper(sel))=0  & pos('?',sel)=0 & noexttype<>"NO"   then do
  823.    if right(sel,1)<>'/' then  do                /* it doesn't end with a */
  824.        foo2=translate(sel,' ','/')
  825.        lastword=word(foo2,words(foo2))  /* extract the last piece */
  826.        foo2=pos('.',lastword)
  827.        if foo2=0 then do                   /*  is no period in the last piece */
  828.              sel=fix_url_ext(sel,noexttype)
  829.              if sel=-1 then do
  830.                    post_filter_message=' / added, and redirected: ' sel
  831.                  signal do_post_filter
  832.              end
  833.        end
  834.    end
  835. end
  836.  
  837. /* 11) See if we should modify urls of the type /xxx/yyy/ */
  838.  
  839.  
  840.  
  841. sel=strip(sel)
  842. selautoname=sel   /* may need to reset sel (see GET verb processing below) */
  843. if pos("CGI-BIN/",upper(sel))>0  | pos('?',sel)>0  | right(sel,1)<>'/' then do
  844.      auto_name=""               /* never check if a mapimage or cgi-bin call */
  845.      first_ht_auto=0
  846. end
  847. else do
  848.     first_ht_auto=1
  849. end
  850.  
  851. goautoname:             /* hop here if no match, auto_name <> "" */
  852. if auto_name<>" "  & right(sel,1)='/' then do     /* some candidate defaults? */
  853.     eek=try_auto_name(sel,auto_name)
  854.     parse var eek sel auto_name
  855. end           /*we may loop here several times, but eventually
  856.                    the auto_names list will be exhausted */
  857.  
  858.  
  859. do_verb:   nop   /* jump here avoids AUTONAME for POST and HEAD */
  860. /* if adv_ops_file specified, then see if there is an EXEC command(s) in it */
  861. if adv_opts<>' ' then do
  862.    tdir=get_value('TEMPFILE_DIR',0)
  863.    gotit=sref_adv_opts_exec(adv_opts,source0,request0,seloriginal,privset,verbose, ,
  864.                             servername,host_nickname,ddir,home_dir,tdir)
  865.    if gotit<>0 then do
  866.         post_filter_message="Advanced Options completed "
  867.         response_status=gotit
  868.         signal do_post_filter
  869.    end
  870. end
  871.  
  872. /* ---------- Process a standard (PUT, DELETE, GET,POST, or HEAD) request  --------------- */
  873.  
  874. /* parse ?xx stuff out */
  875. parse var sel action '?' awords
  876.  
  877. /* .... Now carry out supported verbs (GET POST HEAD POST DELETE ), or SPECIAL control */
  878. /*   -- and check for cgi_bin calls  -- and check for imagemap calls*/
  879.  
  880. /* 12a) First, see if it's an imagemap call */
  881. /* is this a mappable image request (note: add .map if necessary)*/
  882. /* note: href="mapimage/bob.map" in url of /work/hi.htm
  883.          generates call to url of  /work/mapimage/bob.map --
  884.          yielding /work/bob.map )
  885. Check the (several) possible NCSA_ISMAP and CERN_ISMAP strings.
  886. */
  887.    if awords<>' ' then do               /*possible mapimage call */
  888.       jcase=0 ; maptype='NCSA' 
  889.       uaction=upper(action)
  890.       do mm=1 to words(NCSA_ISMAP)      /* check ncsa maps */
  891.           aw=strip(upper(word(ncsa_ismap,mm)))
  892.           if pos(aw,uaction)>0 then do
  893.               jcase=4 ; ismap_url=aw
  894.               leave
  895.           end
  896.       end
  897.       if jcase=0 then do                /*not ncsa, perhaps cern */
  898.          do mm=1 to words(CERN_ISMAP)
  899.             aw=strip(upper(word(CERN_ismap,mm)))
  900.             if pos(aw,uaction)>0 then do
  901.                 jcase=4 ; maptype='CERN' ; ismap_url=aw
  902.                 leave
  903.             end
  904.          end
  905.      end                /* not ncsa map */
  906.  
  907.      if jcase=4 then do         /* process the imagemap -- modify the SEL first */
  908.  
  909.          mapfile0=sref_replacestrg(action,ISMAP_url,"")
  910.          mapfile=do_virtual_file(Ddir,MAPFILE0,,,1)
  911.  
  912.          used_file=mapfile
  913.          select
  914.            when mapfile=0 then
  915.              post_filter_message='Mappable image request, file missing:'||mapfile
  916.            OTHERWISE DO
  917.              MAX_POINTDIST=get_VALUE('MAX_POINTDIST')
  918.              FOO=sref_mapimage(mapfile,awords, servername, serverport, ,
  919.                                tempfile,Ddir, max_pointdist,verbose,mapfile0,maptype)
  920.              post_filter_message='Mappable image request:'||foo
  921.              RESPONSE_STATUS='302 0'
  922.            END
  923.          end            /*SELECT */
  924.  
  925.          signal do_post_filter
  926.      end                /*is a mapimage*/
  927.  
  928.   end                           /* check possible mapinatge */
  929.  
  930.  
  931. /* 12b) second, see if cgi-bin call (and cgi-bin emulation is on */
  932.  
  933. cgi_bin_dir=get_value('CGI_BIN_DIR',0)
  934.  
  935. tsel=strip(upper(sel))
  936. foobao=pos('CGI-BIN/',tsel)
  937. if  (foobao>0) & (cgi_bin_dir<>0)   & (verb="GET" | verb="POST") then do
  938.  
  939.   if no_processing=1 then do                /* no processing allowed */
  940.           response_status=response('unauth',' CGI-BIN processing privileges not granted for: '||sel)
  941.           post_filter_message='CGI-BIN processor: not allowed '
  942.           fpp=stream(tempfile,'c','close')
  943.           signal do_post_filter
  944.   end
  945.  
  946.   if foobao=1 then do                       /* see if alias match */
  947.            selt=translate(sel,' ','\/?')
  948.            aline=wait_queue('ALIAS',word(selt,2))
  949.            parse var aline gotit new_dir
  950.            if gotit<>0 & new_dir<> "" then do
  951.               cgi_bin_dir=strip(translate(new_dir,'\','/'),'t','\')
  952.            end
  953.            selcgi=sel
  954.    end
  955.    else do
  956.          cgipath=left(sel,foobao-1)
  957.          cgi_bin_dir=do_virtual_file(cgi_bin_dir,cgipath,0,0,1)
  958.          selcgi=substr(sel,foobao)
  959.    end
  960.    temfile_dir=get_value('TEMPDATA_DIR',0)
  961.    cmdfile=dostempname(temfile_dir||'\f????.cmd')
  962.    filter_name=get_value('FILTER_NAME',0)
  963.    if clientname0=0 then
  964.    clientname0=clientname()
  965.  
  966.    foox=enmadd' 'transaction' 'home_dir' 'host_nickname
  967.    response_status=sref_docgi(cgi_bin_dir, selcgi, verb, clientname0, filter_name, serverport , ,
  968.         servername, protocol, ddir, who,tempfile,cmdfile,0,VERBOSE,foox,do_htaccess,htaccess_file,privset)
  969.       post_filter_message="CGI-BIN call: "||sel
  970.  
  971.   signal  do_post_filter
  972. end             /* is a cgi-bin call */
  973.  
  974. /* 13) third: special requests */
  975. if left(sel,1)='!' then do
  976.   usel=upper(sel)
  977.   if abbrev(usel,'!DIR')=1 then do
  978.       parse var sel action '?' stuff
  979.       post_filter_message="!DIR processed "
  980.       response_status=sref_dir(ddir,tempfile,action,stuff,tempdata_dir, ,
  981.            dir_cache_duration,dir_cache_size,enmadd, ,
  982.            transaction,verbose,servername,host_nickname,home_dir)
  983.        signal do_post_filter
  984.    end
  985.  
  986.    if abbrev(usel,'!SSI')=1 then do
  987.       parse var sel action '?' args ; args=strip(args)
  988.       if wordpos('SUPERUSER',upper(privset))+wordpos('CONTROL',upper(privset))=0 then do
  989.             post_filter_message="!SSI requires authorization "
  990.             response_status=ask_auth(the_realm)
  991.        end
  992.        else do
  993.          DIRLIST=SERVDIR||' '||CGI_BIN_DIR||' '||DDIR||' '||HOME_DIR
  994.          call check_owner_suppress 
  995.          foo=sref_do_ssi('*'||strip(args),0,0,0,seloriginal,privset,enmadd, ,
  996.                    DIRLIST,verbose,transaction,tempfile,key_preface,,
  997.                    servername||' '||host_nickname,home_name, ,
  998.                    no_processing||' '||no_interpret_code||' '||force_norecord||' '||is_owner_suppress, ,
  999.                    myqueue' 'mysem' 'basesem,who)
  1000.          post_filter_message='SSI processed'
  1001.        end
  1002.        signal do_post_filter
  1003.    end
  1004.  
  1005.   if abbrev(usel,'!AUTH')=1 then do
  1006.             post_filter_message='Force_authorization'
  1007.             response_status=ask_auth(post_filter_message)
  1008.       signal do_post_filter
  1009.   end
  1010.  
  1011. /* otherwise, one of the generic ones */
  1012.    post_filter_message=sref_special_request(sel,privset,the_realm,os2e,enmadd,tempfile)
  1013.    if post_filter_message=-1 then   do  /* !special requests require special privs */
  1014.         response_status=ask_auth(the_realm)
  1015.    end
  1016.    if abbrev(post_filter_message,'Unknown') then do
  1017.          response_status=response('badreq', 'asked for unknown Special control "'sel'"')
  1018.    end
  1019.  
  1020.    signal do_post_filter
  1021. end                    /* Special ! requests */
  1022.  
  1023. /* 14) Fourth:  Process the VERB
  1024.   Currently supported verbs:
  1025.      HEAD: If auto_header, will also parse html file for header instructions
  1026.      GET: Several variants: file transfer, file with ssi, ssp
  1027.      POST: ssp
  1028.      PUT: write a file (given permission exists)
  1029.      DELETE: delete a file (given permission exists)
  1030. In all cases, the url is mapped to a particular file using the
  1031. virtual directory feature (or the data directory if no virtual
  1032. directory matches the requested url).
  1033.  
  1034.  
  1035.    ********************/
  1036. select
  1037. /* 14a) Head Requests */
  1038.  when verb='HEAD' then do
  1039.       file=strip(do_virtual_file(ddir,sel))
  1040.       used_file=file
  1041.  
  1042. /* if forbidden, htaccess will EXIT */
  1043.       if do_htaccess=1 & file<>0  & file<>1 & file<>-1 then do
  1044.            tmp1=sref_htaccess(seloriginal,file,htaccess_file,who,clientname0, ,
  1045.                       whoport,port,ddir,SERVERNAME,TEMPFILE,0)
  1046.            if tmp=-1 then do
  1047.                 response_status='401 - '
  1048.                 post_filter_message='Htaccess denial on HEAD '
  1049.                 signal do_post_filter
  1050.            end
  1051.            parse var tmp1  foo1 ',' file0  ',' nopostf
  1052.            file0=strip(file0) ;
  1053.            if strip(nopostf)=1 then no_postfilter=1
  1054.        end
  1055.  
  1056.       select
  1057.         when file=0 then do
  1058.              response_status= not_found_response(seloriginal,' Document not found ',' ')
  1059.              selrec=' '
  1060.              post_filter_message="HEAD request: Document not found: "||seloriginal
  1061.         end
  1062.         otherwise do
  1063.             post_filter_message="Head request "
  1064.             if auto_header<>"NO" then do
  1065.                   mtype=mediatype(file)
  1066.                   if mtype="text/html" then do
  1067.                       foo= sref_do_auto_header(file,0)     /* sref_do_auto_header will generate the responses */
  1068.                       post_filter_message="Head request with autoheader"
  1069.                    end
  1070.               end   /* AUTOHEADER */
  1071.               response_status='200 '||dosdir(file,'s')
  1072.              if adv_opts<>' ' then foo=sref_adv_opts_header(adv_opts,response_status,servername)
  1073.              'FILE type ' mediatype(file) ' nocache name ' file
  1074.               response_status='200 '||dosdir(file,'s')
  1075.         END             /*OTHERWISE */
  1076.       END               /* SELECT */
  1077.       signal  do_post_filter
  1078.   end                   /* head */
  1079.  
  1080.  
  1081.  when verb="GET" then do
  1082. /* 14b) GET requests  ------------------- */
  1083. /* There are 4 classes of GET requests supported:
  1084.    1) Simple file name  eg;  /ZIPFIP/ZIPFIP.HTM:
  1085.        file is retrived, with possible ssi's
  1086.     2) File name with OPTIONS, eg; /OVERVIEW.HTM?From+ZIPFIP+main+page
  1087.         File is retrieved, with possible ssi's (some of which may use these OPTIONS
  1088.     3) Form name with parameters, eg; /CALC/DOCALC?12-34%2B51
  1089.          sref_getpost is called with appropriate arguments
  1090.     4) Mappable image (ISMAP) response.  URL must include the
  1091.        ncsa_ismap or cern_ismap string (say, MAPIMAGE/) and end with a ?xx,yy.
  1092.        Eg  ISMAPDIR/US/USMAP?41+239
  1093.  
  1094.        Note: ISINDEX type searchable-index requests are identical in
  1095.            appearance to case 2.  To avoid this problem, use the alias_file
  1096.            mechanism (described above) to convert to a class 3
  1097.            ( "form name" SEL) that requests DOSEARCH
  1098. */
  1099.     parse var sel action '?' awords
  1100.     action=TRANSLATE(strip(action))   /* CAP AND Rid  spaces */
  1101.  
  1102.     if  pos('?',sel)=0 then           /* no argument list, must be case 1 */
  1103.           jcase=1
  1104.     else do                   /*arguments, class 2,3, or 4 */
  1105.          attype=mediatype(action)
  1106.          if attype='text/html' then do  /*  CLASS 2 ? */
  1107.              jcase=2            /* class 2: html with "OPTIONS" */
  1108.          end
  1109.          else do                        /* CLASS 3 or 4 */
  1110.               jcase=3              /* case 3: form */
  1111.          end
  1112.      end      /* dtermine jcase */
  1113.  
  1114.  
  1115. /* Do something (depending on jcase */
  1116.      if jcase < 3 then  do   /* genneric file,  or html with options */
  1117.            usef=0 ;   c_type=0 ; a_body=0
  1118.  
  1119.            file=do_virtual_file(ddir,action,,1)
  1120.            used_file=file
  1121.            if do_htaccess=1   & file<>1 & file<>-1 then do
  1122.                tmp1=sref_htaccess(seloriginal,file_nocheck,htaccess_file,who,clientname0, ,
  1123.                       whoport,port,ddir,SERVERNAME,TEMPFILE,0)
  1124.               if tmp1=-1 then do
  1125.                  response_status='401 - '
  1126.                  post_filter_message='Htaccess denial on GET '
  1127.                  signal do_post_filter
  1128.                end
  1129.                parse var tmp1  qca ',' file0  ',' nopostf
  1130.                file0=strip(file0) ;qca=strip(qca)
  1131.                if file0<>0 & first_ht_auto=1 then do
  1132.                   auto_name=file0
  1133.                   first_ht_auto=0
  1134.                end
  1135.                if qca=0 then cache_status='NOCACHE'
  1136.                if strip(nopostf)=1 then no_postfilter=1
  1137.            end
  1138.            select
  1139.              when file=0 | file=-1 then DO
  1140.                if file=-1 | auto_name=" "  then  do /* no directory specific defaults */
  1141.                       response_status=  not_found_response(seloriginal,' Document not found ',not_found_url)
  1142.                       selrec=' '
  1143.                       signal do_post_filter
  1144.                END
  1145.                else do        /* more directory specific defaults to test? */
  1146.                    sel=selautoname
  1147.                    signal goautoname
  1148.                END
  1149.              end
  1150.              when file=1 then do
  1151.                  usef=1
  1152.                  file=a_body
  1153.                  atype=c_type
  1154.              end
  1155.              otherwise
  1156.                 nop
  1157.            End            /* select FILE */
  1158. /* File exists! determine mime type  */
  1159.            if usef=1 then
  1160.               atype=c_type
  1161.            else
  1162.                atype=mediatype(action)
  1163.  
  1164. /* send a byte range request ? */
  1165.            if atype<>'text/html' then do
  1166.              dog=0
  1167.              if del_send<>1 then dog=process_range(file,atype,usef)
  1168.              if dog<>0 then do
  1169.                 post_filter_message='Byte ranges in Non-HTML File sent:'||action
  1170.                 RESPONSE_STATUS='206 '||EXTRACT('BYTESSENT')
  1171.                 signal do_post_filter
  1172.              end
  1173. /* IF HERE, not a byte range request */
  1174.              if usef=0 then do
  1175.                  if del_send=1 then do
  1176.                       response_status='200 '||dosdir(file,'s')
  1177.                       dog='FILE ERASE TYPE '||atype||' NAME '|| file
  1178.                       post_filter_message='Non-HTML File sent & deleted:'||action
  1179.                    end
  1180.                    else do
  1181.                      response_status='200 '||dosdir(file,'s')
  1182.                      dog='FILE TYPE '||atype||" "|| cache_status ||' NAME '|| file
  1183.                      post_filter_message='Non-HTML File sent:'||action
  1184.                    end
  1185.                    fooo=stream(file,'c','close')
  1186.                    if adv_opts<>' ' then foo=sref_adv_opts_header(adv_opts,response_status,servername)
  1187.                    dog
  1188.               end
  1189.               else do   /* REMOTE FILE SEND */
  1190.                    response_status='200 '||length(a_body)
  1191.                    if adv_opts<>' ' then foo=sref_adv_opts_header(adv_opts,response_status,servername)
  1192.                    'VAR TYPE '|| atype|| ' as '|| ACTION ' NAME a_body '
  1193.                    post_filter_message='Remote Non-HTML File sent:'||action
  1194.               end
  1195.               signal do_post_filter
  1196.            end             /* NOT HTML FILE */
  1197.  
  1198. /* else,is html, maybe do ssi's?*/
  1199.           if auto_header="ALWAYS" then
  1200.                foo= sref_do_auto_header(file,usef)     /* sref_do_auto_header will generate EXTRA responses */
  1201.           call check_owner_suppress
  1202.           dofile1=do_includes(file,action,awords,usef)
  1203.           if dofile1=0 then do /* no changes needed (or none attempted), send back requested file */
  1204.               if usef=1 then do  /* FROM REMOTE */
  1205.                    response_status='200 '||length(a_body)
  1206.                    if adv_opts<>' ' then foo=sref_adv_opts_header(adv_opts,response_status,servername)
  1207.                    'VAR TYPE '|| atype|| ' as '|| ACTION ' NAME a_body '
  1208.               end
  1209.               else DO        /* FROM DISK */
  1210.                  if del_send=1 then do
  1211.                     response_status='200 '||dosdir(file,'s')
  1212.                     dog='FILE ERASE TYPE ' atype ||' NAME '|| file
  1213.                     post_filter_message='HTML File sent & deleted:'||action
  1214.                  end
  1215.                  else do
  1216.                     response_status='200 '||dosdir(file,'s')
  1217.                     dog='FILE TYPE 'atype' ' cache_status ||' NAME '|| file
  1218.                     post_filter_message='HTML File sent:'||action
  1219.                  end
  1220.                  if adv_opts<>' ' then foo=sref_adv_opts_header(adv_opts,response_status,servername)
  1221.                  dog
  1222.               end
  1223.           end                   /* DOFILE1=0 */
  1224.           else  do    /* changes were made/results returned, using VAR ,in do_includes */
  1225.             if dofile1<0 then do
  1226.               post_filter_message='Problem sending HTML File (with ssi), probably a broken connection:'||action
  1227.             end
  1228.             else do
  1229.                if del_Send=1 & usef<>1 then do
  1230.                    arf=sysfiledelete(file)
  1231.                    post_filter_message='HTML File sent & deleted (with ssi):'||action
  1232.                end
  1233.                else do    /* STANDARD SSI RETURN -- perhaps from cache */
  1234.                   post_filter_message='HTML File sent (with ssi):'||action
  1235.                   if dofile1<>trunc(dofile1) then
  1236.                      post_filter_message='HTML File sent (from ssi cache):'||action
  1237.                end
  1238.                response_status='200 '||trunc(dofile1)
  1239.             end
  1240.           end
  1241.           if usef=1 then post_filter_message=" Remote "||post_filter_message
  1242.           signal do_post_filter
  1243.  
  1244.      end                /* jcase < 3, file transfer (with includes? */
  1245.  
  1246. /* Note on cache_status. If any kind of logon or access control, then
  1247.    don't cache UNLESS cache specified in access list
  1248.     Also, if byte range sent, no caching.
  1249.           and if ssi's happened, no caching.
  1250. */
  1251.  
  1252.  
  1253. /* IF HERE, jcase=3, ... it's an action request (i.e.; a FORM response) ... */
  1254. /* first, determine if any extra parameters are need, based on ACTION */
  1255.     if no_processing<>1 then do
  1256.            usedfile=' '
  1257.            got1=sref_getpost(tempfile,ACTION,awords,verb,uri,who,servdir,ddir, ,
  1258.                            privset,enmadd,transaction,verbose,serverport,home_dir, ,
  1259.                            servername,host_nickname,do_htaccess,htaccess_file,gp_param||' '||save_state)
  1260.            pod1=word(got1,1)
  1261.            if datatype(pod1)="NUM" then do      /* it's the response status */
  1262.               response_status=subword(got1,1,2)
  1263.               got1=subword(got1,3)
  1264.            end
  1265.            POD=LASTPOS(',',GOT1)
  1266.            IF POD>0 THEN DO
  1267.                   USED_FILE=SUBSTR(GOT1,POD+1)
  1268.                   used_file=strip(used_file)
  1269.                   GOT1=DELSTR(GOT1,POD)
  1270.            END
  1271.            used_file=strip(used_file)
  1272.            post_filter_message=strip(got1)
  1273.      end
  1274.      else do
  1275.           response_status=response('unauth',' Server side processing privileges not granted for: '||action)
  1276.           post_filter_message='Script processor: not allowed '
  1277.      end
  1278.      fpp=stream(tempfile,'c','close')
  1279.      signal do_post_filter
  1280.  
  1281.   end                   /* verb= get */
  1282.  
  1283.  when verb="POST" Then do
  1284.     drop awords
  1285.  
  1286.     'read body var awords'                    /* get the incoming data */
  1287.  
  1288.     if rc=-4 then do                            /* body too large */
  1289.              response_status= response('badreq', 'sent too much data')
  1290.              post_filter_message="POST error: too much data"
  1291.              signal do_post_filter
  1292.     end
  1293.     if rc<>0 then    do                        /* e.g., invalid HTTP header */
  1294.            response_status=response('badreq', 'sent data that could not be read')
  1295.            post_filter_message="POST error: could not read data ="||rc
  1296.            signal do_post_filter
  1297.     end
  1298.  
  1299.  
  1300.     action=TRANSLATE(strip(sel))   /* CAP AND Rid  spaces */
  1301.  
  1302.     if no_processing<>1 then do
  1303.            got1=sref_getpost(tempfile,ACTION,awords,verb,uri,who,servdir,ddir, ,
  1304.                            privset,enmadd,transaction,verbose,serverport,home_dir, ,
  1305.                             servername,host_nickname,do_htaccess,htaccess_file,gp_param||' '||save_state)
  1306.            pod1=word(got1,1)
  1307.            if datatype(pod1)="NUM" then do      /* it's the response status */
  1308.               response_status=subword(got1,1,2)
  1309.               got1=subword(got1,3)
  1310.            end
  1311.            else do
  1312.                 response_status='201 '||extract('bytessent')
  1313.            end
  1314.            POD=LASTPOS(',',GOT1)
  1315.            IF POD>0 THEN DO
  1316.                   USED_FILE=SUBSTR(GOT1,POD+1)
  1317.                   used_file=strip(used_file)
  1318.                   GOT1=DELSTR(GOT1,POD)
  1319.                   ss=dosdir(used_file,'s')
  1320.                   if ss<>' ' then
  1321.                      RESPONSE_STATUS='201 '||DOSDIR(USED_FILE,'S')
  1322.            END
  1323.            used_file=strip(used_file)
  1324.            post_filter_message=strip(got1)
  1325.  
  1326.      end
  1327.      else do
  1328.           response_status=response('unauth',' Server side processing privileges not granted for: '||action)
  1329.           post_filter_message='Script processor: not allowed '
  1330.      end
  1331.      fpp=stream(tempfile,'c','close')
  1332.  
  1333.      signal do_post_filter
  1334.  end
  1335.  
  1336.  when verb="PUT" then do
  1337.    parse var sel action '?' .
  1338.    accept_range=get_value('ACCEPT_RANGE')
  1339.     aa=sref_do_put('PUT',ddir,sel,enmadd,transaction,accopts, ,
  1340.     tempfile,home_dir,servername,host_nickname,accept_range,do_htaccess,htaccess_file)
  1341.     parse var aa aa ',' used_file; aa=strip(aa); used_file=strip(used_file)
  1342.     post_filter_message='PUT request: '||aa
  1343.     signal do_post_filter
  1344.  end
  1345.  
  1346.  when verb="DELETE" then do
  1347.     parse var sel action '?' .
  1348.     accept_range=get_value('ACCEPT_RANGE')
  1349.      aa=sref_do_put('DELETE',ddir,sel,enmadd,transaction,accopts, ,
  1350.             tempfile,home_dir,servername,host_nickname,accept_range,do_htaccess,htaccess_file)
  1351.     parse var aa aa ',' used_file; aa=strip(aa); used_file=strip(used_file)
  1352.     post_filter_message='DELETE request: '||aa
  1353.     signal do_post_filter
  1354.  end
  1355.  
  1356.  
  1357.  
  1358.  otherwise DO
  1359.       if VERBOSE>0 then say " no such verb "
  1360.       RESPONSE_STATUS='501 0'
  1361.       'NODATA '
  1362.  END
  1363.  
  1364. end             /* select verb */
  1365.  
  1366. /* jump here after completion code -- do record option and/or post-filter */
  1367. do_post_filter:
  1368.  
  1369.  
  1370. IF RESPONSE_STATUS=' '  THEN
  1371.   RESPONSE_STATUS='200 '||EXTRACT('BYTESSENT')
  1372.  
  1373. if words(response_status)<2 then do
  1374.   ofo=extract('bytessent')
  1375.   response_status=word(response_status,1)||' '||ofo
  1376. end
  1377.  
  1378. if datatype(strip(word(response_status,2)))<>"NUM" then do
  1379.   ofo=extract('bytessent')
  1380.   response_status=word(response_status,1)||' '||ofo
  1381. end
  1382.  
  1383. /*check for 400 status */
  1384. are1=strip(word(response_status,1))
  1385. if are1>399 then
  1386.    record_option='NO'
  1387. else
  1388.    record_option=strip(get_value('RECORD_OPTION'))
  1389.  
  1390. if verbose>2 then say " Status message: " post_filter_message
  1391. /* check for owner suppression */
  1392.  
  1393. call check_owner_suppress
  1394. if is_owner_suppress=1 then do
  1395.        record_option='NO'
  1396.        if verbose>2 then say " Not recording OWNER or SUPERUSER request "
  1397. end
  1398.  
  1399. post_filter=strip(get_value('POST_FILTER'))
  1400. write_logs=strip(get_value('WRITE_LOGS'))
  1401.  
  1402.  
  1403. if (record_option="NO" & post_filter=0  & write_logs=0) | no_postfilter=1 then do /* nothing to do in post filter */
  1404.    if save_state=1 then foo=sysfiledelete(tcachfile)
  1405.     return ' '
  1406. end
  1407.  
  1408. a=rxqueue('s',enmadd||'POSTF')
  1409. record_all_file=get_value('RECORD_ALL_FILE',0)
  1410. post_filter=get_value('POST_FILTER')
  1411. postfilter_name=get_value('POSTFILTER_NAME')
  1412.  
  1413. selrec=sref_replacestrg(selrec,',','%2c','ALL')
  1414. request0=sref_replacestrg(request0,',','%2c','ALL')
  1415. post_filter_message=sref_replacestrg(post_filter_message,',','%2c','ALL')
  1416.  
  1417. browser=' ';authuser=' '
  1418. thereferer=reqfield('referer')
  1419. if write_logs=1 then do
  1420.   if  clientname0=0 then
  1421.      clientname0=clientname()
  1422.   browser=reqfield('user-agent')
  1423.   goo=reqfield('AUTHORIZATION:')
  1424.   authuser='-'
  1425.   if goo<>" "  then do
  1426.       parse var goo . m64 .              /* get the encoded cookie */
  1427.       dec=pack64(m64)                       /* and decode it */
  1428.       parse upper var dec authuser ':' .      /* split to userid */
  1429.   end
  1430. end
  1431.  
  1432. fuse=' '
  1433. if save_state=1 then do
  1434.    tdir=strip(TEMPDATA_DIR,'t','\')||'\'
  1435.    fuse=dostempname(tdir||'_T??????.TMP')
  1436.    foo2=dosrename(tcachfile,fuse)
  1437.    if foo2=0 then fuse=' '
  1438. end
  1439. queue  record_option ',' record_all_file ',' post_filter ',' postfilter_name ',' serverport ',' ,
  1440.                  post_filter_message ',' source0 ',' request0 ',' got_def' 'selrec ',' ,
  1441.                 tempfile ','  servername ',' host_nickname ',' used_file ',' who ',' ,
  1442.                 enmadd ',' thereferer ',' fuse ',' RESPONSE_STATUS ',' write_logs ',' ,
  1443.                 clientname0 ',' authuser ',' browser ',' verbose
  1444. aa=eventsem_post(basesem||'POSTF')
  1445. return ' '  /* note that postfilter and recorder don't need to tell the filter anything*/
  1446.  
  1447. /***********/
  1448. /* check on owner suppression */
  1449. check_owner_suppress:
  1450. chkowner=get_value('HIT_OWNER_SUPPRESS')
  1451.  
  1452. is_owner_suppress=0
  1453. if chkowner=1 then do
  1454.   if owners=' ' then owners=get_value('Owners')
  1455.   chkowner2=0
  1456.   if hit_superuser_suppress=1 then chkowner2=wordpos('SUPERUSER',privset)
  1457.   if wordpos(who,owners)>0 | chkowner2>0 then do
  1458.        is_owner_suppress=1
  1459.   end
  1460. end
  1461. return is_owner_suppress
  1462.  
  1463.  
  1464.  
  1465.  
  1466. /***************/
  1467. /* create a personallized queue & semaphore */
  1468. make_semmi:
  1469. a=rxqueue('s',myqueue)
  1470. noq=1
  1471. signal on syntax name badq
  1472. queue 0
  1473. noq=0
  1474. badq:
  1475. signal off syntax
  1476. if noq=1 then do
  1477.   IF VERBOSE>0 THEN say " creating myqueue " myqueue
  1478.   foo=rxqueue('c',myqueue)
  1479.   if upper(foo)<>upper(myqueue) then
  1480.        say ' wierd queue error ' foo myqueue
  1481.   a=rxqueue('s',myqueue)
  1482. end
  1483. yyq=queued()
  1484. if yyq>100 then do
  1485.   if verbose>1 then say " Killing residual queue " myqueue yyq
  1486.   aa2=rxqueue('d',myqueue)
  1487.   aa2=rxqueue('c',myqueue)
  1488.   aa2=rxqueue('s',myqueue)
  1489.   yyq=queued()
  1490. end
  1491. do mmy=1 to yyq
  1492.     pull poo .
  1493. end
  1494.  
  1495. wow=eventsem_query(mysem)
  1496. if wow=-187 then do
  1497.    a=eventsem_create(mysem)
  1498.    if a=0  then do
  1499.        nop
  1500.   end
  1501.   else do
  1502.      call pmprintf(' Could not create semaphore: 'mysem' , error='a)
  1503.      response_status=response('notfound', ' server is busy, try later')
  1504.      dienow=0
  1505.      return 0
  1506.    end
  1507. end
  1508. foo=eventsem_reset(MYSEM)
  1509. dienow=1
  1510. return 1
  1511.  
  1512.  
  1513.  
  1514. /* ------------------------------------- */
  1515. /* subroutine to strip & set !directives. Sets several globals
  1516.  so call as routine, not procedure  */
  1517.  
  1518. modify_seloriginal:
  1519.  
  1520. /* special "force authorization" request */
  1521. force_auth=0
  1522. if abbrev(upper(seloriginal),'!FORCE')=1 then do
  1523.    seloriginal=substr(seloriginal,8)
  1524.    selrec=seloriginal
  1525.    force_auth=1
  1526. end
  1527.  
  1528. force_norecord=0
  1529. if abbrev(upper(seloriginal),'!NORECORD')=1 then do
  1530.    seloriginal=substr(seloriginal,11)
  1531.    selrec=seloriginal
  1532.    if no_no_record<>1 then force_norecord=1
  1533. end
  1534.  
  1535. specific_mime=0
  1536. if abbrev(upper(seloriginal),'!SENDAS_')=1 then do
  1537.    ooy=pos('/',seloriginal)
  1538.    ooy2=pos('?',seloriginal)
  1539.    if ooy2>0 & ooy2< ooy then ooy=ooy2
  1540.    if ooy>0 then do
  1541.       specific_mime=substr(seloriginal,9,ooy-9)
  1542.       seloriginal=substr(seloriginal,ooy+1)
  1543.       selrec=seloriginal
  1544.   end
  1545.   else do
  1546.       specific_mime=substr(seloriginal,9)
  1547.       seloriginal=' '
  1548.       selrec=seloriginal
  1549.   end
  1550. end
  1551.  
  1552. del_send=0
  1553. if abbrev(upper(seloriginal),'!DELSEND')=1 then do
  1554.    seloriginal=substr(seloriginal,10)
  1555.    selrec=seloriginal
  1556.    del_send=1
  1557. end
  1558.  
  1559. return
  1560.  
  1561. /* ------------------------------------------------ */
  1562. /* routine to get privileges (sets privset global). DOES not get public_privs*/
  1563. get_user_privs:
  1564.   parse arg noadd,noinh
  1565.   privset=privset||' '||check_user_info(who,1,noadd)  /* auth, and possibly add-user, privs */
  1566.  
  1567.  if noinh<>1 then do
  1568.      call goodips(who)  /* is this an inhouse connect - get some privs! */
  1569.      isin=result
  1570.      if isin<>0 then   privset=PRIVSET||' '||inhouse_privs||' '||privset1
  1571.   end
  1572.  
  1573.   RETURN
  1574.  
  1575.  
  1576. /******************************************************************************/
  1577. /*-- DO_prefiltr: Call User Written pre-filter(s)                  --**/
  1578. /******************************************************************************/
  1579.  
  1580. do_prefiltr: procedure expose source0 request0 seloriginal prefilter_name verbose ,
  1581.               transaction servername host_nickname
  1582.   parse arg amessage
  1583.   signal on syntax name bad2a
  1584.   signal on error name bad2a
  1585.   foo3=' '
  1586.  
  1587. /* note that results from earilier pre-filters are sent do later ones */
  1588.   do mm=1 to words(prefilter_name)
  1589.       aname=word(prefilter_name,mm)
  1590.       yow='foo3='||aname||'(source0,request0,seloriginal,amessage,servername,foo3)'
  1591.       interpret yow
  1592.  
  1593.       if completed() then leave  /* leave if pre-filter handled the request */
  1594.          parse var foo3 status ',' prefilter_result
  1595.          status=strip(status)
  1596.         if status=1 then leave
  1597.   end
  1598.  
  1599.  signal off syntax
  1600.  signal off error
  1601. return foo3
  1602.  
  1603.  
  1604. bad2a:          /* jump here on syntax error */
  1605.   signal off syntax
  1606.   signal off error
  1607.   call pmprintf(" Error in pre-filter routine " aname)
  1608.   return amessage
  1609.  
  1610.  
  1611.  
  1612.  
  1613. /* ----------------------------------------------------------------------- */
  1614. /* Already completed (cache or prefilter. Record it and exit            */
  1615. /* ----------------------------------------------------------------------- */
  1616. done_it:                        /* need globals, so call as routine */
  1617.  parse arg status , amessage
  1618.     issent=0
  1619.     if datatype(status)<>'NUM' then status=0
  1620.     if status=0 then issent=completed()
  1621.     if (issent+status)=0 then return 0   /* otherwise exit */
  1622.  
  1623.     if VERBOSE>1 then call pmprintf(" Completed or redirected request: " amessage)
  1624.     parse var sel action '?' awords
  1625.      return 1
  1626.  
  1627.  
  1628. /* ----------------------------------------------------------------------- */
  1629. /* RESPONSE: Standard [mostly error] responses.
  1630.    It calls a macrospace routine that does the work                        */
  1631. /* ----------------------------------------------------------------------- */
  1632. response: procedure expose tempfile  seloriginal request0 source0 verbose ,
  1633.         transaction servername host_nickname tempfile
  1634. parse arg request, message
  1635. foo=sref_response(request,message,tempfile,servername)
  1636. return foo
  1637.  
  1638.  
  1639.  
  1640.  
  1641. /* ----------------------------------------------------------------------- */
  1642. /* NOT_FOUND_RESPONSE: Return "not found" response, use macrospace routine */
  1643. /* ----------------------------------------------------------------------- */
  1644. not_found_response: procedure expose tempfile  verbose  transaction servername host_nickname seloriginal a_body
  1645.   parse arg request, message , message2
  1646.  
  1647. a=sref_not_found_response(request, message , message2, tempfile,verbose,transaction,servername,host_nickname,seloriginal)
  1648. return a
  1649.  
  1650.  
  1651. /* ------------------------------------------------------ */
  1652. /* query and wait on helper threads */
  1653. /* ------------------------------------------------------*/
  1654. wait_queue: procedure expose os2e mysem myqueue enmadd basesem  ,
  1655.           mytid verbose  transaction no_virtual servername host_nickname 
  1656. parse arg athread,args,extra1
  1657. athread=strip(athread) ; args=strip(args)
  1658. /* check to see if no need to call queue */
  1659.  
  1660. a1=check_queue_do(athread,enmadd,args,extra1)
  1661. parse var a1 istat ',' ires
  1662. if istat=1 then do
  1663.    ires=strip(ires)
  1664.    return ires
  1665. end
  1666.  
  1667. again1t:
  1668.  
  1669. goober=enmadd||athread
  1670.   a=rxqueue('s',goober)
  1671.   queue  transaction ' ' host_nickname ',' myqueue ',' mysem ','  ARGS
  1672.  
  1673.   a=eventsem_reset(mysem)
  1674.   dothread=basesem||athread
  1675.  
  1676.   a=eventsem_post(dothread)
  1677. again2t:
  1678.   a=eventsem_wait(mysem)
  1679.  
  1680.   if a<>0 then do
  1681.         call pmprintf(mytid','athread' A Fatal Semaphore failure: 'a)
  1682.         String 'Web server is temporarily busy '
  1683.         exit ' '
  1684.   end
  1685.   a=rxqueue('s',myqueue)
  1686.  
  1687.   parse pull aline
  1688.   PARSE VAR ALINE idnum ',' aline
  1689.   idnum=strip(translate(idnum,' ','000d0a'x));TRANSACTION=STRIP(TRANSACTION)
  1690.   if idnum<>transaction then  do /*wierd error: got someone else's message! */
  1691.       say ' Read odd id from queue 'athread ':' transaction ',' idnum
  1692.       if eventsem_query(mysem)=1 then aa=eventsem_reset(mysem)
  1693.      signal again2t
  1694.   end
  1695.  
  1696.   aline=strip(aline)
  1697.   return aline
  1698.  
  1699.  
  1700. /*-------------------------------------------------*/
  1701. /* - Check auto_name list (ONLY called if xxx/yyy/ type of url) ? */
  1702. /* ---------------------------------*/
  1703. try_auto_name: procedure expose verbose  transaction servername host_nickname seloriginal
  1704. parse arg sel1,auto_name
  1705.      lensel1=length(sel1)
  1706.      tryme=strip(word(auto_name,1))
  1707.      auto_name=delword(auto_name,1,1)  /* remove it from list */
  1708.      ttryme=upper(tryme)
  1709.      select
  1710.          when abbrev(ttryme,"!CREATE")=1 |  abbrev(ttryme,'!DIR')=1 then do   /* use sref_dir to create a file listing*/
  1711.                 sel1='!dir?/'||sel1
  1712.          end
  1713.          when translate(tryme)="!SHOWDIR" then do /* use the builddir ddlp */
  1714.                    sel1='showdir?/'||sel1
  1715.          END            /*SHOWDIR IS A SRE-FILTER FRONT END TO VARIOUS DDLP OF GOHTTP */
  1716.          when abbrev(tryme,'*')=0 then do
  1717.             if pos('/',tryme)=1 | pos(':',tryme)>0 then
  1718.                 sel1=tryme
  1719.             else
  1720.                 sel1=sel1||tryme
  1721.           end
  1722.           otherwise  do         /* *, *.htm, *.html, etc. */
  1723.             foo2=lastpos('/',sel1,lensel1-1)
  1724.             parse var tryme ast "." ext
  1725.             if ext="" then ext="htm"
  1726.             sel1=sel1||substr(sel1,foo2+1,lensel1-(1+foo2))||'.'||ext
  1727.           end
  1728.      end             /* select */
  1729.      if VERBOSE>0 then say "Trying auto-named sel = " sel1
  1730.      return sel1 auto_name
  1731.  
  1732.  
  1733.  
  1734.  
  1735. /***************************************************************************/
  1736. /* ---------- ----------------------- ----------*/
  1737. /* LOGON checking. If no user match, requery client*/
  1738. /* -----------------------------------------------------------------------*/
  1739.  
  1740. do_logon: procedure expose inhouseips. enmadd os2e the_realm clientname0 ,
  1741.                    mysem myqueue basesem mytid verbose  transaction no_virtual ,
  1742.                    servername host_nickname logon_limit logon_fail_file ,
  1743.                    seloriginal force_auth gotauser tempfile
  1744.  
  1745.   parse arg anip , inhouse_privs
  1746.  
  1747.   gotauser=1             /* assume success */
  1748.  
  1749. /* see if an inhouseips. */
  1750.   call goodips(anip)
  1751.   if result=1 then do
  1752.      if clientname0=0 then
  1753.          myname=clientname()
  1754.       else
  1755.          myname=clientname0
  1756.       parse var myname myname1
  1757.       ptmp=inhouse_privs||' '||privset1
  1758.  
  1759.       stuff=check_user_info(who)
  1760.       parse var stuff lstat .
  1761.       if strip(lstat)>0 then do
  1762.          parse var stuff uu privset2
  1763.          ptmp=ptmp||' '||privset2
  1764.        end
  1765.       return  1 myname1 ptmp
  1766.   end
  1767. /* not inhouse, check if user info available.  */
  1768.   stuff=check_user_info(anip)
  1769.  
  1770.   parse var stuff lstat . ; lstat=strip(lstat)
  1771.  
  1772. /* valid username? return stuff */
  1773.  
  1774.   if lstat > 0 then return   stuff
  1775.  
  1776. /* no such user: either ask again, or send a "failure" response file */
  1777.    gotauser=0
  1778.    if logon_fail_file=0 | reqfield('Authorization')=' ' |force_auth=1  then do
  1779.  
  1780.         return ask_auth(the_realm)   /* ask again */
  1781.    end
  1782.  
  1783. /* if here, respond with generic "logon fail file". Note use of amess to
  1784.    differentiate username failure from logon-limit exceeding */
  1785.    awebmaster=get_value('WEBMASTER')
  1786.    if logon_limit >= -lstat | logon_limit=0 then
  1787.         amess="Incorrect username or password "
  1788.    else
  1789.         amess="Too many logon attempts per minute "
  1790.    return sref_fail(servername,seloriginal,logon_fail_file,verbose,the_realm,'logon failure',awebmaster,amess)
  1791.  
  1792.  
  1793.  
  1794.  
  1795.  
  1796. /* ------------------------------------------- */
  1797. /* check request header for auth, return user info if found and valid user
  1798. if privsonly=1, just return privileges (user specific, and possibly "own name"*/
  1799. /* ------------------------------------------- */
  1800.  
  1801. check_user_info: procedure expose mysem myqueue basesem enmadd os2e,
  1802.              mytid verbose  transaction no_virtual servername host_nickname
  1803. parse arg anip,PRIVSONLY,noadd
  1804. FO=0 ; IF PRIVSONLY=1 THEN FO=""
  1805.  
  1806.   goo=reqfield('AUTHORIZATION:')
  1807.   if goo=" "  then
  1808.        return FO
  1809.    parse var goo . m64 .              /* get the encoded cookie */
  1810.    dec=pack64(m64)                       /* and decode it */
  1811.    parse upper var dec user ':' pwd      /* split to userid and password */
  1812. /* get info from user thread */
  1813.   anarg=User||' '||pwd||' '||anip
  1814.  
  1815.   stuff=wait_queue('USER',anarg)
  1816.  
  1817.   parse var stuff astatus privset1
  1818.   IF verbose>2 THEN SAY " User logon info: " stuff
  1819.  
  1820.    if noadd<>1 then do
  1821.      addname=get_value('add_user_name')
  1822.      if user<>'*' then do
  1823.        if addname=1 then privset1=privset1||' '||user
  1824.      end
  1825.   end
  1826.  
  1827.   IF PRIVSONLY=1 THEN RETURN PRIVSET1
  1828.  
  1829.   if astatus>0 then
  1830.       return 1 user privset1
  1831.  
  1832.   return astatus
  1833.  
  1834.  
  1835.  
  1836. /* -----------------------------------------------------------------------*/
  1837. /* see if ip address matches one of a set of good ips (1 if yes)*/
  1838. /* check for numeric or names ,and check for wildcards */
  1839. /* if non-default host, ONLY get "Host specific" inhouseips */
  1840. /* -----------------------------------------------------------------------*/
  1841. goodips: procedure expose inhouseips. privset1 enmadd os2e verbose  transaction servername host_nickname ,
  1842.                    clientname0
  1843.  
  1844.  
  1845. parse arg anips
  1846.  
  1847. anips=strip(anips) ;hostn=strip(host_nickname)
  1848.  
  1849. if symbol(inhouseips.0)<>"VAR" then do  /* not been read yet */
  1850.    aa='inhouseips.' ;addit=''
  1851.    if hostN<>"" then addit='.'||hostn
  1852.    nin=0
  1853.    do mm=1 to 10000
  1854.       useme=enmadd||aa||mm||addit ; useme=strip(useme)
  1855.       tt=strip(value(useme,,os2e))
  1856.       if tt="" | tt=0 then leave
  1857.       nin=nin+1 ; inhouseips.nin=upper(tt)
  1858.    end
  1859.    inhouseips.0=nin
  1860. end
  1861.  
  1862. /* check exact matches -- perhaps name matches */
  1863. mdo=inhouseips.0
  1864. do mm=1 to mdo
  1865.   if inhouseips.mm=' '  then iterate
  1866.   if verify(word(inhouseips.mm,1),'*1234567890.')=0 then do  /*a numeric ip */
  1867.      if word(inhouseips.mm,1)=anips then do        /*it's an exact match -- extract privset */
  1868.         parse var inhouseips.mm ff  privset1
  1869.         return 1
  1870.     end
  1871.   end
  1872.   else do                      /* a name ip */
  1873.       if clientname0=0 then clientname0=upper(clientname())
  1874.       if word(inhouseips.mm,1)=clientname0 then do        /*it's an exact match -- extract privset */
  1875.          parse var inhouseips.mm ff  privset1
  1876.          return 1
  1877.       end
  1878.   end           /* name or number inhouseip */
  1879. end
  1880.  
  1881. /* if here, try wild card matches */
  1882. parse var anips ip.1 '.' ip.2 '.' ip.3 '.' ip.4 .
  1883. if clientname0<>0 then
  1884.       parse var clientname0  cip.1 '.' cip.2 '.' cip.3 '.' cip.4 .
  1885.  
  1886. do m2=1 to mdo           /* wild card matches */
  1887.      if inhouseips.m2=' ' then iterate
  1888.      if pos('*',inhouseips.m2)=0 then iterate
  1889.      match=1
  1890.      parse var inhouseips.m2 uip.1 '.' uip.2 '.' uip.3 '.' uip.4 privset1
  1891.      do mm2 =1 to 4
  1892.        if uip.mm2="*" then iterate
  1893.        if uip.mm2=ip.mm2 then iterate
  1894.        if clientname0<>0 then 
  1895.            if uip.mm2=cip.mm2 then iterate
  1896.        match=0       /*if here, not a match */
  1897.        leave
  1898.      end
  1899.      if match=1 then return 1
  1900. end
  1901. return 0                /* no match */
  1902.  
  1903.  
  1904. /*--------------------------------------------------*/
  1905. /* check user privileges (privset) against a url specific privilege list (aprivs)
  1906. if one of them matches, return >0 value
  1907. if no match, return 0 */
  1908. /* ----------------------------------------------- */
  1909.  
  1910. check_privs: procedure  expose verbose  transaction servername host_nickname ,
  1911.             who enmadd servdir
  1912. parse upper arg privset , aprivs
  1913.  
  1914. /* check MUST_HAVE privilegs */
  1915.  
  1916. if pos('&',aprivs)>0 then do
  1917.    musthaves=""
  1918.    oneofs=""
  1919.    do jj=1 to words(aprivs)             /* extrace MUST_HAVE privs */
  1920.         ajj=strip(word(aprivs,jj))
  1921.         if abbrev(ajj,'&')=1 then
  1922.                 musthaves=musthaves||' '||ajj
  1923.         else
  1924.                 oneofs=oneofs||' '||ajj
  1925.    end
  1926.    do jj=1 to words(musthaves)
  1927.         avi=strip(word(musthaves,jj))
  1928.         ajj=strip(avi,'l','&')
  1929.         if wordpos(ajj,privset)=0 then do       /* must have ALL must_have privs */
  1930.             return 0
  1931.         end
  1932.    end
  1933.    aprivs=oneofs
  1934. end
  1935.  
  1936.  
  1937. /* check ONE_OF privileges */
  1938. select
  1939.     when wordpos('SUPERUSER',privset)>0 then
  1940.         return 1
  1941.     when wordpos('NO',aprivs)>0 then do
  1942.         return 0
  1943.     end
  1944.     when aprivs="" | wordpos('*',aprivs)>0 | wordpos('YES',aprivs)>0 then do
  1945.         return 1
  1946.     end
  1947.     otherwise do
  1948.        do mm=1 to words(aprivs)
  1949.           if wordpos(word(aprivs,mm),privset)>0 then do
  1950.                return mm
  1951.           end
  1952.        end
  1953.     end         /* otherwise */
  1954.  end    /* select */
  1955.  
  1956.  return 0
  1957.  
  1958.  
  1959.  
  1960. /* -----------------------------------------------------------------------*/
  1961. /* Query client for authorization stuff.  */
  1962. ask_auth:procedure expose verbose  transaction servername host_nickname tempfile
  1963. PARSE ARG R1, R2
  1964. IF R2="" THEN
  1965.   AREALM=R1
  1966. ELSE
  1967.   AREALM=R2
  1968.  
  1969. 'header add WWW-Authenticate: Basic Realm=<'||arealm|| '>'  /* challenge */
  1970. foo=response('unauth', "for realm " arealm " was not authorized")
  1971. return foo
  1972.  
  1973.  
  1974. /* ----------------------------------------------- */
  1975. /* find virtual file name, or perform a remote lookup possibly
  1976. returns
  1977.   file name if local file found
  1978.   0 if no success in finding local file
  1979.   If remoteok=1 the ...
  1980.      -1 if can't get remote file, or not allowed to get it
  1981.       1 if could get remote file, with info in c_type and a_body exposed variables
  1982.  
  1983.    if not_f=1, does the "doc not found" to goserv (if 0, does not respond to client)
  1984.    nocheck=1 -- suppress the nochcek (1= do NOT check for the file's existence) */
  1985. /* ----------------------------------------------- */
  1986. do_virtual_file:procedure expose os2e mysem myqueue enmadd basesem  servername serverport tempfile ,
  1987.               mytid verbose  transaction no_virtual c_type a_body host_nickname file_nocheck
  1988.  
  1989.  
  1990. parse arg ddir,sel,not_f,remoteok,nocheck
  1991. crlf    ='0d0a'x                        /* constants */
  1992.   parse var sel action '?' .
  1993.   file=wait_queue('VIRTUAL',action||' '||ddir)
  1994.  
  1995.   if abbrev(upper(file),'HTTP:\\')=1 then do
  1996.       file=translate(file,'/','\')
  1997.       if remoteok<>1 then return -1        /* do not allow remote "virtual directory*/
  1998.       tfile=sref_get_remote(file,verbose)
  1999.       if tfile=0 then do
  2000.           return -1
  2001.        end
  2002.        parse var tfile c_type (crlf) a_body
  2003.        return 1
  2004.    end
  2005.  
  2006.    file_Nocheck=file  /* used by htaccess routines */
  2007.  
  2008.    if nocheck<>1  then do
  2009.      rf=stream(file,'c','query exists')
  2010.      if rf="" then do
  2011.         if not_f<>" " then do
  2012.            return not_found_response(sel,'Document not found ',not_f)
  2013.         end
  2014.         return 0
  2015.      end
  2016.    end
  2017.    return file
  2018.  
  2019.  
  2020. /*----------------------------------------------*/
  2021. /* fix up extension free url's (after aliasing)
  2022.     Note that if ?xx appears after a extension-free action (say,
  2023.     yyy/xxx?abc), then we assume that this is an action request.
  2024. Otherwise, depending on value of noexttype
  2025.   DIR: treat it as a "non-root directory's default document, but they forgot
  2026.       the final /".
  2027.  HTM or HTML : Add .HTM or .HTML respectively
  2028.   NONE : leave it be
  2029. */
  2030. fix_url_ext: procedure expose verbose  transaction servername host_nickname serverport
  2031. parse arg sel, noexttype
  2032.     select
  2033.           when noexttype="DIR" then do
  2034.              sel=sel||'/'                /* tIt's a directory*/
  2035.              if VERBOSE>0 then say " Using  DIR re-named Sel: " sel
  2036.            end
  2037.           when noexttype="REDIR" then do
  2038.              sel=sel||'/'                /* tIt's a directory*/
  2039.              foo=isa_move('!MOVED '||sel,servername,serverport)
  2040.              return -1
  2041.            end
  2042.  
  2043.            when noexttype="HTM" then do
  2044.               sel=sel||".HTM"           /* fat style html file */
  2045.               if VERBOSE>0 then say " Using .HTM re-named Sel: " sel
  2046.            end
  2047.            when noexttype="HTML" then do
  2048.               sel=sel||".HTML"          /* html file */
  2049.               if VERBOSE>0 then say " Using .HTML re-named Sel: " sel
  2050.            end
  2051.            when noexttype="NONE" then do
  2052.                nop                      /* leave it be */
  2053.            end
  2054.            otherwise do
  2055.                sel=sel||noexttype    /* user specified (experimental!) */
  2056.                if VERBOSE>0 then say " Using other re-named Sel: " sel
  2057.            end
  2058.    end             /* if select (sel does not end with name.ext) */
  2059.    return sel
  2060.  
  2061.  
  2062.  
  2063.  
  2064. /* -----------------------------------------------------------------------*/
  2065. /* check for a "range request". If none found, then return 0.
  2066.    Else, return an appropriate VAR response, or if multiple
  2067.    sends, a 1
  2068. For details on range retrieval, see draft-ieft-http-range-retrieval-00.txt
  2069. (Luotonen and Franks, 2/22/96)
  2070. (try ds.internic.net)
  2071. */
  2072. /* -----------------------------------------------------------------------*/
  2073.  
  2074. process_range: procedure expose enmadd os2e verbose  transaction servername host_nickname
  2075.  
  2076.   parse arg afile,atype,usef
  2077. /* do we want to check ranges ? */
  2078.   accept_range=get_value('ACCEPT_RANGE')
  2079.   if accept_range<>1 then
  2080.         return 0
  2081.  
  2082.   ranges=reqfield('range:')
  2083.   if ranges="" then do
  2084.     'HEADER ADD Accept-Ranges: bytes '
  2085.      return 0
  2086.   end
  2087.  
  2088. /* check for tentative and insertion headers.
  2089. i)    Unless-modified-since: day, 15 Nov 1995  06:25:55 GMT
  2090. ii)    If-modified-since: day, 15 Nov 1995 06:25:55 GMT
  2091.  If exist, compare against date of file.
  2092. i) If modified since date, return 0 (that is, treat as a non-range
  2093.    request
  2094. ii) If not modified, return a 304 Not Modified response.
  2095.  
  2096. If a If-Valid appears, return 0 (sre-filter does not support If-valid)
  2097. If a If-Invalid appears, ignore.
  2098. ************/
  2099.  
  2100. tm1=REQFIELD('If-Valid')
  2101. if tm1<>'' then return 0
  2102.  
  2103. numeric digits 11
  2104.  
  2105. /* files timestamp date */
  2106. fildate=dosfileinfo(afile,'W')  /* mm/dd/yy hh:mm:ss */
  2107. parse var fildate d1 d2
  2108. filetime=dateconv(d1,'u','b')+cvt_time_frac(d2)
  2109.  
  2110. wow1=reqfield('If-modified-since:')
  2111. if wow1<>"" then do
  2112.    parse var wow1 eek ',' dd mm year  atime agmt
  2113.    asktime=dateconv(dd' 'mm' 'year,'N','B')+cvt_time_frac(atime)
  2114.    goff=gmtoffset() ; if datatype(goff)<>'NUM' then goff=0
  2115.    if gmt<>'' then asktime=asktime+ (goff/(24*60*60))
  2116.  
  2117.    if filetime<asktime then do
  2118.           'RESPONSE HTTP/1.0 304 Not Modified'  /* Set HTTP response line */
  2119.           'STRING  Resource not modified since requested date '
  2120.            return '304 0'
  2121.     end
  2122. end
  2123.  
  2124. wow1=reqfield('Unless-modified-since')
  2125. if wow1<>"" then do
  2126.    parse var wow1 eek ',' dd mm year  atime agmt
  2127.    asktime=dateconv(dd' 'mm' 'year,'N','B')+cvt_time_frac(atime)
  2128.    goff=gmtoffset() ; if datatype(goff)<>'NUM' then goff=0
  2129.    if gmt<>'' then asktime=asktime+ (goff/(24*60*60))
  2130.    if filetime>asktime then return 0  /* modified, better send everything */
  2131. end
  2132.  
  2133.  wow=sref_process_range(afile,atype,ranges,usef)
  2134.  if wow=0 then do
  2135.     'HEADER ADD Accept-Ranges: bytes '
  2136.   end
  2137.   return wow
  2138.  
  2139. /* ** convert hh:mm:ss to fraction of a day */
  2140. cvt_time_frac:procedure
  2141. parse arg d2
  2142. parse var d2 hr ':' min ':' sec
  2143. secs=(hr*60*60)+(min*60)+(sec)
  2144. fsecs=secs/(24*60*60)
  2145. return fsecs
  2146.  
  2147.  
  2148.  
  2149. /* ----------------------------------------------------------------------- */
  2150. /* SEND_NON_DATADIR -- !TRANSFER -- Send a file not in the data directory
  2151.  This is basically obsolete, but is retained for occassional use
  2152.  Use at  analias !TRANSFER=X:\DIR\FILE.NAM
  2153. */
  2154. /* ----------------------------------------------------------------------- */
  2155.  
  2156. send_non_datadir: procedure expose tempfile verbose  transaction servername host_nickname ,
  2157.                                 specific_mime
  2158. parse upper arg taction
  2159. taction=strip(taction)
  2160. if abbrev(taction,'!TRANSFER=')=1 then
  2161.    taction=delstr(taction,1,10)
  2162. else
  2163.   return not_found_response(taction,' Could not transfer file ',' ')
  2164.  
  2165. action=translate(taction,'\','/')
  2166. a=stream(action,'c','query exists')
  2167. if a="" then do
  2168.   return not_found_response(action,' No file to transfer',' ')
  2169.  
  2170. end
  2171.  
  2172. 'FILE TYPE ' mediatype(a)  ' nocache NAME' a
  2173. return '200 '||dosdir(a,'s')
  2174.  
  2175. /* --------------------------------------------------- */
  2176. /* take care of server side includes
  2177. .  If none (or no_include=yes, or is not shtml?), then return 0 -- which means
  2178. .      "go ahead and return the default document, and maybe cache it? "
  2179. */
  2180. /* --------------------------------------------------- */
  2181.  
  2182. do_includes:procedure expose tempfile no_include os2e enmadd key_preface,
  2183.           cgi_bin_dir seloriginal privset servdir verbose  transaction ddir ,
  2184.           home_dir servername host_nickname home_name no_processing myqueue adv_opts,
  2185.           ssi_extensions who no_interpret_code force_norecord mysem basesem force_auth is_owner_suppress
  2186.  
  2187.  parse  arg tfile,sel0,awords,usef
  2188.  
  2189.  
  2190.   if no_include=1 then  /* don't bother, just return original file */
  2191.         return 0
  2192.  
  2193.  ssi_shtml_only=get_value('SSI_SHTML_ONLY')
  2194.  
  2195. /* if shtml mode, check if its an .sht[ml] file */
  2196.  if ssi_shtml_only=1 then do
  2197.      FOO1=LASTPOS('.',sel0)
  2198.      if foo1=0 then return 0                /*no extenstion!*/
  2199.      anext=upper(delstr(sel0,1,foo1))
  2200.      if wordpos(anext,upper(ssi_extensions))=0 then
  2201.          return 0
  2202.  end
  2203.  
  2204.  
  2205.  
  2206.  if usef<>1 then do
  2207.     foo=stream(tfile,'c','query exists')
  2208.     if foo=0 | foo="" then do              /*problem opening ! */
  2209.       if VERBOSE>0 then say " Could not open file for includes : " tfile
  2210.       return 0          /* just send back file as is */
  2211.     end
  2212.  end
  2213. /* sref_do_includes */
  2214.  
  2215.  tmp1=get_value('SSI_CACHE_ON')
  2216.  ssic=0
  2217.  if tmp1=0 then ssic=1
  2218.  if  force_auth=1 then  ssic=1
  2219.  DIRLIST=SERVDIR||' '||CGI_BIN_DIR||' '||DDIR||' '||HOME_DIR
  2220.  gotit=sref_do_ssi(tfile,usef,sel0,awords,seloriginal,privset,enmadd, ,
  2221.                    DIRLIST,verbose,transaction,tempfile,key_preface,,
  2222.                    servername||' '||host_nickname,home_name, ,
  2223.                    no_processing||' '||no_interpret_code||' '||force_norecord||' '||is_owner_suppress,,
  2224.                    myqueue' 'mysem' 'basesem,who,ssic,adv_opts)
  2225.  return gotit
  2226.  
  2227.  
  2228. /**********************************************/
  2229. /* check to see if we need NOT call one of the helper threads */
  2230. /**********************************************/
  2231. check_queue_do:procedure expose no_virtual servername host_nickname 
  2232. parse arg athread,enmadd,args,allow1
  2233. os2e='os2environment'
  2234.  
  2235. select
  2236.   when athread="ALIAS" then do
  2237.      aaa=get_value('SUPPRESS_ALIAS',0)
  2238.      if aaa=1 then do
  2239.            return ' 1  , 0 '|| args
  2240.       end
  2241.   end
  2242.   when athread="USER" then do
  2243.       if get_value('SUPPRESS_USER',0)=1 then do
  2244.           yo=get_value('CHECKLOG')
  2245.           if yo="NO" then
  2246.              return ' 1 , 1 '
  2247.           else
  2248.              return ' 1, 0 '
  2249.       end
  2250.   end
  2251.   when athread="ACCESS" then do
  2252.       if get_value('SUPPRESS_ACCESS',0)=1 then  do
  2253.            return ' 1 , 0 '
  2254.       end
  2255.       if allow1="YES_NOCHECK" then do
  2256.            return ' 1 , 0 '
  2257.       end
  2258.   end
  2259.   when athread="VIRTUAL" then do
  2260.      if no_virtual=0 then
  2261.         no_virtual=get_value('SUPPRESS_VIRTUAL',0)
  2262.      if no_virtual=1 then do
  2263.         parse var args action ddir
  2264.        t1=strip(strip(translate(ddir,'\','/')),,'\')||'\'
  2265.        action=translate(action,'\','/')
  2266.        action=strip(action,'l','\')
  2267.        tryfile=t1||action
  2268.        return '1 ,'||tryfile
  2269.      end
  2270.   end
  2271.   otherwise DO
  2272.         return' 0 , 0 '
  2273.   END
  2274. end
  2275.  
  2276. RETURN ' 0 ,0'
  2277.  
  2278.  
  2279. /* ------------------*/
  2280. /* see if this parameter applies to this host */
  2281. /* ------------------*/
  2282. check_host: procedure
  2283. parse upper arg thehost,thearg
  2284. f1=strip(word(thearg,1))
  2285. if right(f1,2)<>'//' then return thearg       /* non host specific */
  2286. t1=left(f1,length(f1)-2)
  2287. if thehost=t1 then return strip(delword(thearg,1,1)) /* strip host and return */
  2288.  
  2289. return ' '               /* 0 signifies don't use */
  2290.  
  2291. /* ----------- */
  2292. /* get environment value, possibly host specific
  2293. hname=0 -- do not look under hostname
  2294. hname=1 -- do not look under default
  2295.  */
  2296. /* ------------ */
  2297. get_value: procedure expose enmadd host_nickname
  2298. parse upper arg vname,hname0
  2299. if hname0=0 then
  2300.         hname=' '
  2301. else
  2302.     hname=strip(host_nickname)
  2303.  
  2304. vname=strip(vname) ;
  2305. if hname<>' ' then do
  2306.    booger=strip(enmadd||vname||'.'||hname)
  2307.    aval=value(booger,,'os2environment')
  2308.    if aval<>' ' | hname0=1 Then
  2309.         return aval
  2310. end
  2311. aval=value(enmadd||vname,,'os2environment')
  2312. return aval
  2313.  
  2314.  
  2315.  
  2316. /* --------------------------------- */
  2317. /* detect a "moved" url (from an alias) -- calls macrospace routine */
  2318. isa_move:procedure expose tempfile verbose   servername  seloriginal
  2319. parse arg sel,servername ,serverport
  2320.  
  2321. sel=strip(sel)
  2322. tsel=upper(translate(sel,'/','\')) ;a1=left(tsel,1)
  2323. if a1='!' | a1='H' then do
  2324.    wow=sref_isa_move(tsel,sel,servername,serverport,tempfile,verbose,seloriginal)
  2325.    return wow
  2326. end
  2327. return 0
  2328.  
  2329.  
  2330. /*  Determine MIME type.  Check the most common ones here,
  2331. and if no match, call the more elaboate routine (in macrospace).
  2332. This more elaborate one also will examine mediatyp.rxx */
  2333.  
  2334. mediatype:procedure expose specific_mime
  2335.  
  2336. /* if specific_mime<>0, then use it! */
  2337.  if specific_mime<>0 then do
  2338.      aa=translate(specific_mime,' ','_')
  2339.      m1=strip(word(aa,1)); m2=strip(word(aa,2))
  2340.      foof=m1||'/'||m2
  2341.      return foof
  2342.  end
  2343.  
  2344. /* else, use file extension */
  2345.   parse arg aval
  2346.  
  2347.  
  2348.   ext=translate(substr(aval, lastpos('.',aval)+1))
  2349.   if wordpos(ext,'HTM HTML SHTML SHTM HTML-INCLUDE ')>0 then
  2350.         return ' text/html'
  2351.   if ext='GIF' then return 'image/gif'
  2352.   return sref_mediatype(aval)
  2353.  
  2354. /* ----------------------------------------------------------------------- */
  2355. /* SREF_FAIL: Return a "no acCESS here" response file (and exit)
  2356.   or returns 0 (caller should do an ask_auth)    */
  2357. /* ----------------------------------------------------------------------- */
  2358. sref_fail:procedure expose the_realm urlrealm 
  2359. parse arg aserver,AURL,a2,verbose,the_realm,errmess,awebmaster,tellmess
  2360.  
  2361.    if a2=' ' | a2=1 then return 0
  2362.  
  2363.    eek=stream(a2,'c','query exists')
  2364.    if eek<> ' 'then do
  2365.  
  2366.       atype=sref_mediatype(a2)
  2367.       if upper(atype)="TEXT/HTML" then do
  2368.           booger=charin(a2,1,chars(a2))
  2369.           booger=strip(booger,'t','1a'x)
  2370.           booger=sref_insert_block(booger,'#URL',aurl,1,'<!--','-->')
  2371.             alink=' <a href="/!FORCE?'||aurl||'"> Try again? </a>'
  2372.           booger=sref_insert_block(booger,'#LINK',alink,1,'<!--','-->')
  2373.           booger=sref_insert_block(booger,'#WEBMASTER',awebmaster,1,'<!--','-->')
  2374.           booger=sref_insert_block(booger,'#MESSAGE',tellmess,1,'<!--','-->')
  2375.           a_body=sref_insert_block(booger,'#SERVER',aserver,1,'<!--','-->')
  2376.  
  2377.          
  2378.          'VAR TYPE '|| atype|| ' as '|| '/'||aurl|| ' NAME a_body '
  2379.           return '401 '||length(a_body)
  2380.       end
  2381.       else do
  2382.                  'FILE TYPE ' atype  ' NOCACHE NAME ' a2
  2383.                 return '401 '||dosdir(a2,'s')
  2384.       end
  2385.    end
  2386.    else do
  2387.      if verbose>0 then say " Warning: Non-existent " errmess " response file:" a2
  2388.      return ask_auth(the_realm,urlrealm)
  2389.    end
  2390.  
  2391.  
  2392.